将大量命中记录到MySQL数据库的最佳实践

时间:2011-05-17 13:12:48

标签: php mysql caching

嗯,这就是事情。假设我未来的PHP CMS需要每天驱动500k访问者,我需要将它们全部记录在MySQL数据库中(引用者,IP地址,时间等)。这样我需要每分钟插入300-500行并更新50行。主要问题是每次我想插入新行时脚本都会调用数据库,这是每次有人点击页面时。

我的问题是,有没有办法首先在本地缓存传入的命中(对于那个apc,csv ......最好的解决方案是什么?)并定期每隔10分钟将它们发送到数据库?这是一个很好的解决方案,这种情况的最佳做法是什么?

10 个答案:

答案 0 :(得分:22)

每天500k,每秒只有5-7个查询。如果每个请求的服务时间为0.2秒,那么您将几乎同时进行0次查询,因此无需担心 即使你的用户数量增加了5倍 - 所有用户都可以正常工作 您可以使用INSERT DELAYED并调整您的mysql 关于调整:http://www.day32.com/MySQL/ - 有非常有用的脚本(不会改变任何内容,只是向您展示如何优化设置的提示)。

你可以先使用memcache或APC在那里写日志,但是使用INSERT DELAYED MySQL会做几乎相同的工作,并且会做得更好:)

请勿使用此文件。 DB将比PHP更好地提供锁。编写有效的互斥锁并不是那么简单,所以让DB(或memcache,APC)完成这项工作。

答案 1 :(得分:18)

经常使用的解决方案:

您可以在memcached中实现一个计数器,您可以在访问时增加该计数器,并且每100次(或1000次)点击就会对数据库进行更新。

答案 2 :(得分:4)

我们这样做是通过在每台服务器上本地存储到CSV,然后有一个微小的cron作业将条目推送到数据库中。这是为了避免需要高度可用的MySQL数据库 - 数据库应该能够毫无问题地处理该数量的插入。

答案 3 :(得分:3)

将它们保存到基于目录的数据库(或平面文件,取决于)某处,并在某个时间,使用PHP代码将它们插入/更新到MySQL数据库中。您的PHP代码可以使用Cron定期执行,因此请检查您的服务器是否具有Cron,以便您可以设置该计划,例如每10分钟一次。

查看此页面:http://damonparker.org/blog/2006/05/10/php-cron-script-to-run-automated-jobs/。有些代码已在云中编写,可供您使用:)

答案 4 :(得分:2)

一种方法是使用 Apache access.log。通过使用带有apache的 cronolog 实用程序,您可以获得非常好的日志记录。 Cronolog将处理文件中大量行的存储,并可根据卷日,年等轮换它。使用此实用程序将阻止您的Apache遭受日志写入。

然后正如其他人所说,使用基于cron的作业来分析这些日志,并在MySQL中推送您想要的任何汇总或原始数据。

您可以考虑使用专用数据库(甚至数据库服务器)进行具有特定设置的写密集型作业。例如,您可能不需要InnoDB存储并保留简单的MyIsam。你甚至可以想到另一个数据库存储(如@Riccardo Galli所说)

答案 5 :(得分:2)

如果您绝对需要直接登录MySQL,请考虑使用两个数据库。一个针对快速插入进行了优化,这意味着除了可能的auto_increment主键之外没有其他键。还有另一个带有您要查询的所有内容的按键,针对快速搜索进行了优化。定时作业会定期将命中数据从仅插入数据库复制到只读数据库,最终您将获得两全其美的效果。唯一的缺点是您的可用统计信息只会与之前的“复制”运行一样新鲜。

答案 6 :(得分:2)

我之前也看到过一个系统,它将数据记录到每个Web服务器上本地磁盘上的一个平面文件中(如果使用多个过程,请小心只做原子附加),并定期将它们异步写入数据库中。守护进程或cron作业。

这似乎是流行的优化解决方案;如果审计数据库关闭,您的Web应用程序仍然可用,如果数据库因任何原因而变慢,则用户不会遇到性能不佳。

我唯一可以说的是,确保您对这些本地生成的文件进行监控 - 构建肯定表明存在问题,而您的Ops工程师可能不会注意到。

答案 7 :(得分:0)

对于大量的写操作和这类数据,你可能会发现更合适的mongodb或couchdb

答案 8 :(得分:0)

由于INSERT DELAYED仅支持MyISAM,因此它不适用于许多用户。

我们使用MySQL Proxy来推迟与特定签名匹配的查询的执行。

这需要一个自定义的Lua脚本; example scripts are heresome tutorials are here

该脚本将实现用于存储查询字符串的Queue数据结构,以及用于确定要延迟的查询的模式匹配。一旦队列达到一定大小,或者经过了一定的时间,或者发生了X事件,查询队列就会被清空,因为每个查询都会被发送到服务器。

答案 9 :(得分:0)

您可以使用beanstalk或IronQ

来使用队列策略