【问题标题】:Best practice to record large amount of hits into MySQL database将大量点击记录到 MySQL 数据库中的最佳实践
【发布时间】:2011-08-27 05:44:09
【问题描述】:

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

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

【问题讨论】:

  • 另外,在那个大桌子上跟踪唯一个访问者(每个 IP 地址)的最佳方式是什么?
  • SELECT DISTINCT ( ip ) FROM access_log

标签: php mysql caching


【解决方案1】:

您可以使用 beanstalk 或 IronQ 使用队列策略

【讨论】:

    【解决方案2】:

    由于INSERT DELAYED 仅受MyISAM 支持,因此对于许多用户来说不是一个选项。

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

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

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

    【讨论】:

      【解决方案3】:

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

      这似乎是流行的最佳解决方案;如果审核数据库关闭,您的 Web 应用程序仍然可用,并且如果数据库因任何原因变慢,用户不会遭受性能不佳的影响。

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          每天 50 万次,每秒只有 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 以获得更完整的答案和INSERT DELAYED的讨论
          【解决方案6】:

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

          看看这个页面:http://damonparker.org/blog/2006/05/10/php-cron-script-to-run-automated-jobs/。部分代码已编写在云端,可供您使用:)

          【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

            对于大量写入操作和此类数据,您可能会找到更合适的 mongodb 或 couchdb

            【讨论】:

            • 对于明智的报告,您将需要 SQL。这不是“大量的写操作”。尝试在 XXXdb 中进行 GROUP BY(用你最喜欢的 nosql 替换 XXX)
            【解决方案9】:

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

            【讨论】:

              【解决方案10】:

              一个常用的解决方案:

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

              【讨论】:

              • 拥有内存缓存而不是文件缓存(如其他答案)要快得多! +1
              猜你喜欢
              • 2010-10-11
              • 2016-08-21
              • 2012-01-10
              • 2015-10-17
              • 1970-01-01
              • 2020-01-11
              • 2011-04-10
              • 2021-08-22
              • 2013-06-30
              相关资源
              最近更新 更多