处理并发的PHP页面缓存?

6
我已经阅读了关于PHP缓存的先前答案以及它们链接到的文章。我已经查看了经常推荐的Pear Cache_Light,QuickCache和WordPress Super Cache。要么没有处理并发问题,要么在其文档中没有明确指出。有人能指导我使用处理并发的PHP页面缓存吗?由于这是共享主机,因此memcache和opcode缓存不可行。我不使用模板引擎,并希望避免依赖于一个。 WP Super Cache的方法是首选的-即在wwwroot下存储静态文件以让Apache提供服务-但不是必需的。谢谢!P.S.自动处理的示例包括:1. Apache / PHP缓存正在读取缓存文件。缓存文件变为过时并尝试删除。2.删除了缓存文件,因为它已过时。请求该文件的请求正在进行中,而该文件正在重新创建的过程中。另一个请求也在此期间进入。
6个回答

2
似乎 PEAR::Cache_Lite 有一些安全措施来处理并发问题。 如果您查看 constructor Cache_Lite::Cache_Lite 的手册,您会看到以下选项:
文件锁定(fileLocking):启用/禁用文件锁定。可以在不良情况下避免缓存损坏。
写入控制(writeControl):启用/禁用写入控制。启用写入控制将轻微减慢缓存写入速度,但不会影响缓存读取。写入控制可以检测到一些损坏的缓存文件,但可能不是完美的控制。
读取控制(readControl):启用/禁用读取控制。如果启用,控制键将嵌入到缓存文件中,并与读取后计算出的键进行比较。
读取控制类型(readControlType):读取控制类型(仅在启用读取控制时)。必须为“md5”(用于MD5哈希控制(最佳但速度最慢)),“crc32”(用于CRC32哈希控制(稍微不太安全但速度更快))或“strlen”(仅用于长度测试(速度最快))。
选择使用哪种控制方式仍然取决于您愿意牺牲什么样的性能,以及您的应用程序中可能存在的并发访问风险。
您可能还想看一下Zend_Cache_Frontend_Output,使用类似Zend_Cache_Backend_File这样的后端缓存页面。
那个似乎也支持某种安全性--与Cache_Lite提供的相同类型的东西(所以我不会再复制粘贴一次)。
另外,如果您的网站在共享主机上运行,我想它没有那么多用户?因此,并发访问的风险可能不是那么高,对吧?
无论如何,我可能不会搜索比这两个框架更远的地方:对于您的应用程序的需求来说,它已经足够了 :-)
“我从未见过比这些机制更安全的缓存机制……而且在三年的PHP开发中,我从未遇到过类似的灾难性并发问题……无论如何,祝你玩得愉快!”

Pear Cache_Light无法处理所有并发问题 - 例如,在文件被锁定以进行写入时从缓存中读取。 (或者也许我应该说:并发问题被推迟到应用程序代码中。)对我来说是不可行的。您问:“...因此,并发访问的风险可能不是很高,对吗?”虽然访问显然遵循更大的趋势(例如,中午更多,星期三更多),但每秒钟的页面请求是随机的。并发对于所有网站都是一个问题。 - WalterGR

1

我会想要修改现有的缓存之一。Zend Framework 的缓存应该能够胜任。如果不行的话,我会进行更改。

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

这将处理您的 ACID 问题。您可以为某个人的更新设置很短的锁定期限,或者根据您的服务器负载/容量和生产缓存内容的成本,在那个往返中完全跳过缓存。

Jacob


1

并发资源创建,也称为缓存撞击/线程竞争,在繁忙的网站上可能是一个严重的问题。因此,我创建了一个缓存库,它同步读/写进程/线程。

它具有优雅和清晰的结构:接口 -> 适配器 -> 类,易于扩展。在github页面上,我详细解释了撞击的问题以及该库如何解决它。

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


0
在Linux下,通常情况下,即使文件被“删除”,它仍然会保持“打开”状态,直到进程关闭该文件。这是系统内置的功能,有时可能会导致磁盘使用量大小出现巨大差异(在文件仍处于“打开”状态时删除一个3G文件意味着该文件仍然被分配在磁盘上作为正在使用,直到进程关闭它)-我不确定在Linux下是否也是如此。
假设使用日志文件系统(大多数Linux文件系统和NTFS)-那么在进程关闭文件之前,该文件不应被视为“已创建”。这应该显示为不存在的文件!

感谢您的编辑,这很有启发性。P.S.中的“发生了什么?”问题只是修辞手法。我已经更新了问题以反映这一点。 - WalterGR
啊!我忘记在问题标题中写了“实现/查找”。 我删除了“实现”。如果需要的话,我会再开一个问题。再次感谢。 - WalterGR

0
假设使用日志文件系统(大多数Linux文件系统和NTFS) - 在进程关闭文件之前,该文件不应被视为“已创建”。这应该显示为不存在的文件!
不,它创建后就可见,您必须锁定它。 但是重命名是原子的。因此,您可以打开(open(),写入(write(),关闭(close(),重命名(rename()),但这将无法防止同时重新创建相同的缓存项两次。
缓存文件因过时而被删除。 请求该文件并正在重新创建文件时会出现另一个请求此文件的情况。
如果没有锁定,则会提供半成品文件,或两个进程将尝试同时生成相同的文件,从而产生“有趣”的结果。

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

谢谢。虽然数据库可以避免由于ACID中的“C”而可能出现的文件损坏问题,但仍有其他事项需要正确处理,例如ACID中的“I”。这不仅仅是“创建一个数据库表”的问题。 - WalterGR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接