好的,这是关键。假设我的未来 PHP CMS 需要每天处理 500k 访问者并将它们全部记录在 MySQL 数据库中(referrer、ip 地址、时间等)。这意味着我需要每分钟插入 300-500 行数据并更新 50 行。主要问题是每次有人打开页面时,脚本都会调用数据库以插入新行。
我的问题是,是否有任何方法可以首先在本地缓存传入的点击量(最好的解决方案是什么,apc、csv...?),然后每隔 10 分钟将它们定期发送到数据库?这是一个好的解决方案吗?对于这种情况,最佳实践是什么?
每天500k的请求只相当于每秒5-7个查询。如果每个请求的服务时间为0.2秒,则几乎没有同时查询,所以不用担心。
即使用户数增加五倍,一切也应该正常运作。
你可以使用INSERT DELAYED并调整mysql。
关于调整:http://www.day32.com/MySQL/ - 这里有一个非常有用的脚本(它不会改变任何设置,只是向你展示如何优化设置)。
你可以使用memcache或APC先将日志写入其中,但使用INSERT DELAYED MySQL将几乎完成同样的工作,并且做得更好 :)
请不要使用文件进行这种操作。数据库会比PHP更好地提供锁定服务。编写有效的互斥量并不那么轻松,因此让数据库(或memcache、APC)来完成这项工作。
INSERT DELAYED
的讨论。 - Kevin Peno经常使用的解决方案:
您可以在memcached中实现一个计数器,每次访问都会加一,并在累计到100(或1000)个点击时向数据库推送更新。
一种方法是使用Apache访问日志。您可以使用cronolog实用程序和Apache一起获得相当好的日志记录。Cronolog将处理大量行的存储,并且可以根据容量、天数、年份等进行旋转。使用此实用程序将防止Apache遭受日志写入。
然后,正如其他人所说,使用基于cron的作业来分析这些日志,并将您想要的任何汇总或原始数据推送到MySQL中。
您可以考虑使用专用数据库(甚至是数据库服务器)进行写入密集型作业,并进行特定设置。例如,您可能不需要InnoDB存储并保持简单的MyIsam。您甚至可以考虑使用另一个数据库存储(如@Riccardo Galli所说)。
我之前看到过一个系统,它会将数据记录到每个Web服务器的本地磁盘上的一个平面文件中(如果使用多处理器,请只进行原子追加),然后通过守护进程或定时任务周期性地异步写入数据库。
这似乎是当前最优解决方案;如果审计数据库宕机,您的Web应用程序仍然可用,并且如果由于任何原因数据库变慢,用户也不会遭受低性能的影响。
唯一需要注意的是,确保对这些本地生成的文件进行监控 - 如果堆积了大量文件,则表示存在问题,否则您的Ops工程师可能不会注意到。
如果需要进行大量写操作并处理此类数据,您可能会发现mongodb或couchdb更适合。
由于INSERT DELAYED
仅受MyISAM
支持,因此对于许多用户来说这不是一个可选项。
我们使用MySQL Proxy来延迟执行与特定签名匹配的查询。
这将需要一个自定义的Lua脚本; 示例脚本在此处, 和 一些教程在此处。
该脚本将实现一个队列数据结构用于存储查询字符串,并进行模式匹配以确定要推迟哪些查询。一旦队列达到一定大小,或经过一定时间,或发生任何事件X,查询队列将被清空,因为每个查询都会发送到服务器。
你可以使用Beanstalk或IronQ来实现队列策略
SELECT DISTINCT ( ip ) FROM access_log
- genesis