将大量匹配logging到MySQL数据库的最佳实践

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

我的问题是,有什么办法来本地caching传入命中(以及什么是最好的解决scheme,apc,csv …?),并定期例如每10分钟发送到数据库? 这是一个好的解决scheme,这种情况下的最佳做法是什么?

每天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)来完成这个工作。

经常使用的解决scheme:

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

我们通过在每台服务器上本地存储到CSV来完成此操作,然后执行一个精细的cron作业以将条目推送到数据库中。 这是为了避免需要高度可用的MySQL数据库 – 数据库应该能够处理插入的数量没有问题。

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

看看这个网页: http : //damonparker.org/blog/2006/05/10/php-cron-script-to-run-automated-jobs/ 。 一些代码已经写在云中,并准备好让你使用:)

一种方法是使用Apache access.log。 你可以通过使用cronolog实用程序和apache来获得相当好的日志logging。 Cronolog将处理文件中大量行的存储,并可以根据卷日,年等进行旋转。使用此实用程序可以防止Apache受到日志写入的困扰。

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

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

如果您绝对需要直接login到MySQL,请考虑使用两个数据库。 一个针对快速插入进行了优化,这意味着除了可能的auto_increment主键之外,没有其他键。 而另一个关键的东西你会查询,优化快速search。 一个定时的工作将定期从插入到单一的数据库复制点击,并最终与两全其美。 唯一的缺点是,你可用的统计数据只会和以前的“复制”一样新鲜。

我以前也见过一个系统,它将数据logging到每个Web服务器上的本地磁盘上的一个平面文件中(如果使用多个过程,请小心使用primefaces追加),并使用守护进程定期asynchronous地将它们写入数据库, cron工作。

这似乎是普遍的最佳解决scheme; 如果审计数据库closures,且您的Web应用程序仍然可用,并且数据库由于任何原因而速度较慢,则用户不会遇到糟糕的性能。

我唯一能说的就是确保你对这些本地生成的文件进行监视,这样的构build肯定表明了一个问题,你的Ops工程师可能没有注意到。

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

因为INSERT DELAYED只被MyISAM支持,所以对许多用户来说这不是一个选项。

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

这将需要一个自定义的Lua脚本; 示例脚本在这里 , 一些教程在这里 。

该脚本将实现一个队列数据结构来存储查询string,并通过模式匹配来确定要推迟的查询。 一旦队列达到一定的大小,或者经过了一定的时间,或者发生了任何事件X,查询队列就会被清空,因为每个查询都被发送到服务器。

您可以使用豆浆或IronQ使用队列策略