【问题标题】:Page cache in PHP that handles concurrency?PHP中处理并发的页面缓存?
【发布时间】:2009-08-04 08:17:52
【问题描述】:

我在这里阅读了有关 PHP 缓存的先前答案,以及它们链接到的文章。我查看了经常推荐的 Pear Cache_Light、QuickCache 和 WordPress Super Cache。 (抱歉 - 显然我只能超链接一次。)

要么没有人处理并发问题,要么没有人在他们的文档中明确指出他们这样做。

谁能告诉我处理并发的 PHP 页面缓存的方向?

这是在共享主机上,因此很遗憾内存缓存和操作码缓存不是一个选项。我不使用模板引擎,并希望避免依赖模板引擎。 WP Super Cache 的方法更可取 - 即将静态文件存储在 wwwroot 下以让 Apache 为它们提供服务 - 但不是必需的。

谢谢!

附:应该自动处理的事情的例子:

  1. Apache / PHP 缓存正在读取缓存文件。缓存文件已过时并尝试删除。
  2. 缓存文件已过时而被删除。收到对该文件的请求,并且正在重新创建该文件。 另一个文件的请求在此期间进来。

【问题讨论】:

    标签: php caching


    【解决方案1】:

    似乎 PEAR::Cache_Lite 具有某种安全性来处理并发问题。
    如果您查看constructor Cache_Lite::Cache_Lite 的手册,您有以下选择:

    文件锁定 启用/禁用文件锁定。可以避免坏下的缓存损坏 情况。

    writeControl 启用/禁用写控制。启用写控制会稍慢 缓存写入但不是缓存 阅读。写控制可以检测到一些 损坏的缓存文件,但也许不是 完美的控制。

    读取控制 启用/禁用读取控制。如果启用,将嵌入控制键 缓存文件和这个键进行比较 与之后计算的一个 阅读

    readControlType 读取控制的类型(仅当启用读取控制时)。必须是“md5” (对于 md5 哈希控制(最好但 最慢)),'crc32'(用于 crc32 哈希 控制(稍微不安全,但 更快))或“strlen”(一段长度 只测试(最快))

    使用哪一个仍然取决于您,并且取决于您准备牺牲哪种性能 - 以及您的应用程序中可能存在的并发访问风险。


    您可能还想查看Zend_Cache_Frontend_Output,以缓存页面,使用类似Zend_Cache_Backend_File 作为后端。

    那个似乎也支持某种安全性——Cache_Lite 已经给你的同样的东西(所以我不会第二次复制粘贴) p>


    作为旁注,如果您的网站在共享主机上运行,​​我想它没有 那么多 用户?那么并发访问的风险大概没有那么高吧?

    无论如何,我可能不会再搜索那些框架所建议的内容:它可能已经足以满足您的应用程序的需求了 :-)

    (我从来没有见过任何缓存机制比那些允许你做的“更安全”......而且我从来没有遇到过这种灾难性的并发问题......在 3 年内PHP 开发)


    无论如何:玩得开心!

    【讨论】:

    • Pear Cache_Light 不能处理所有并发问题 - 例如,当文件被锁定以进行写入时从缓存中读取。 (或者我应该说:并发问题是针对应用程序代码的。)这对我来说是不行的。你问,“......所以并发访问的风险可能没有那么高,是吗?”虽然访问显然遵循更大的趋势(例如,中午更多,星期三更多),但从一秒到一秒的页面请求是随机的。并发是所有网站的问题。
    【解决方案2】:

    我很想修改现有的缓存之一。 Zend Framework 的缓存应该可以解决问题。如果没有,我会改变它。

    您可以创建一个非常原始的锁定策略。该数据库可用于跟踪所有缓存的项目,允许锁定更新,允许人们等待其他人的更新完成,...

    这将解决您的 ACID 问题。您可以将其他人的更新锁定设置为非常短的时间,或者可能让它完全跳过该往返的缓存,具体取决于您的服务器负载/容量和生成缓存内容的成本。

    雅各布

    【讨论】:

      【解决方案3】:

      在繁忙的网站上,并发资源创建(即缓存撞击/线程竞争)可能是一个严重的问题。这就是为什么我创建了同步读/写进程/线程的缓存库。

      它具有优雅而清晰的结构:接口 -> 适配器 -> 类,便于扩展。在 github 页面上,我详细解释了 slamming 的问题以及图书馆如何解决它。

      在这里查看: https://github.com/tztztztz/php-no-slam-cache

      【讨论】:

        【解决方案4】:
        1. 在 Linux 下,通常,文件将保持“打开”状态以供读取,即使它在进程关闭文件之前已“删除”。这是系统内置的东西,有时会导致磁盘使用大小出现巨大差异(在它仍然“打开”时删除 3G 文件意味着它仍然在磁盘上分配,直到进程关闭它) - 我'我不确定在linux下是否也是如此。
        2. 假设一个日志文件系统(大多数 Linux 文件系统和 NTFS) - 那么在进程关闭文件之前,该文件不应被视为“已创建”。这应该显示为一个不存在的文件!

        【讨论】:

        • 编辑谢谢,这是信息。 “会发生什么?” P.S.中的问题只是修辞。我已更新问题以反映这一点。
        • 确认!我忘记了我在问题标题中写了“实施/发现”。我删除了“实施”。如果涉及到这一点,我将打开另一个问题。再次感谢。
        【解决方案5】:

        假设日志文件系统(大多数 Linux 文件系统和 NTFS)- 那么文件不应该被视为“创建”,直到该过程 关闭文件。这应该显示为一个不存在的文件!

        不,它一创建就可见,您必须锁定它。 重命名虽然是原子的。所以你可以 open()、write()、close()、rename(),但这不会阻止同一个缓存项同时被重新创建两次。

        缓存文件已过时而被删除。 收到对该文件的请求,并且正在重新创建该文件。在此期间另一个文件请求进来了。

        如果它没有被锁定,将提供一个半完整的文件,或者两个进程会尝试同时重新生成同一个文件,给出“有趣”的结果。

        【讨论】:

          【解决方案6】:

          您可以在数据库中缓存页面,只需创建一个简单的“名称,值”表并将缓存页面存储在上面。

          【讨论】:

          • 谢谢。虽然数据库可以避免文件可能出现的损坏问题(由于 ACID 中的“C”),但还有其他事情需要正确处理,例如酸中的“我”。这不是“只创建一个数据库表”的问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-13
          • 2018-11-08
          • 2013-05-24
          • 2015-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多