2011-05-17 19 views
40

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

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

+1

另外一个队列策略,什么是对那个大表来跟踪(每个IP地址)** **唯一访问者的最佳方式? – livelygreen 2011-05-17 14:55:47

+0

'SELECT DISTINCT( ip ) FROM access_log' – genesis 2011-06-18 23:11:12

回答

22

每天500k它只是每秒5-7个查询。如果每个请求的服务时间为0.2秒,那么您几乎可以同时进行0次查询,所以没有什么可担心的。
即使你将有5倍的用户 - 所有应该工作正常。
你可以使用INSERT DELAYED并调整你的mysql。
关于调整:http://www.day32.com/MySQL/ - 有非常有用的脚本(将不会改变,只是告诉你如何优化设置的提示)。

您可以使用内存缓存或APC写日志有第一,但使用的延迟插入MySQL会做几乎同样的工作,并会做的更好:)

不要使用文件这一点。 DB会比PHP更好地提供锁定。编写有效的互斥锁并不那么简单,所以让DB(或者memcache,APC)来完成这个工作。

+0

+1,以获得更完整的回答和“INSERT DELAYED” – 2011-05-17 15:58:09

18

经常使用的解决方案:

你可以实现你上访问增加memcached一个计数器,并推动更新到数据库中每100(或1000)命中。

+4

拥有内存缓存而不是文件缓存(就像在其他答案中一样)速度要快得多! +1 – 2011-05-17 13:28:52

4

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

3

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

看看这个网页:http://damonparker.org/blog/2006/05/10/php-cron-script-to-run-automated-jobs/。有些代码已经写在云端,随时供您使用:)

+0

无法在页面上下载文件crontab.php http://damonparker.org/blog/2006/05/10/php-cron-script-to-run-automated-jobs/“ – xuesong 2011-05-17 14:15:13

+0

因此请尝试找到一个不同的脚本:)互联网上有成千上万的文章 – 2011-05-17 15:42:06

+0

博客文章不存在了...... – Malachi 2015-05-29 19:17:12

0

对于大量写操作,这类型的数据你可能会发现更适合的MongoDB或CouchDB的

+0

而对于明智的报告,您将需要SQL,这不是“大量的写操作” 。尝试在XXXDB中执行GROUP BY(用您最喜欢的nosql替换XXX) – MarkR 2011-05-17 14:15:09

2

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

然后如别人所说,使用基于cron的作业来分析这些日志,并推送您想要的所有MySQL数据。

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

2

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

2

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

这似乎是普遍的最佳解决方案;如果审计数据库关闭,且您的Web应用程序仍然可用,并且由于任何原因数据库速度较慢,则用户的性能不会受到影响。

我唯一可以说的就是确保你对这些本地生成的文件进行监视 - 建立一个确定的问题,你的Ops工程师可能不会注意到。

0

因为INSERT DELAYED只支持MyISAM,所以它不是许多用户的选项。

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

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

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

0

您可以使用使用青苗或IronQ