如何使用后台作业缓存页面?

时间:2010-05-14 17:47:39

标签: php ruby-on-rails zend-framework caching

说明:resource =数据库记录的集合,再生=处理这些记录并输出相应的html

当前流程:

  • 接收客户请求
  • 检查缓存中的资源
  • 如果未在缓存或缓存中过期,请重新生成
  • 返回结果

问题在于,重新生成步骤可以将单个服务器进程占用10-15秒。如果有几个用户请求相同的资源,那么可能会导致几个进程同时重新生成完全相同的资源,每个进程占用10-15秒。

让前端信号的某些后台程序说“嘿,为我重新生成这个资源”,这不是一件好事吗。

但是它会向用户显示什么? “重建”是不可接受的。所有资源都必须提前在缓存中。这可能是一个问题,因为数据库几乎会在文件系统上重复(太大而不适合内存)。有办法避免这种情况吗?不理想,但似乎是唯一的出路。

但是还有一个问题。如何保持相同的两个进程同时请求资源的重新生成?当前端请求重新生成相同资源时,后台进程可以重新生成资源。

我正在使用PHP和Zend Framework,以防有人想要提供特定于平台的解决方案。但这并不重要 - 我认为这个问题适用于任何语言/框架。

谢谢!

5 个答案:

答案 0 :(得分:2)

使用Varnish,您可以主动缓存页面内容,并在响应未及时返回时使用宽限期显示过时的缓存内容。

  

启用宽限期(varnish在从后端重新获取对象时提供过时(但可缓存)对象)

您可能需要调整拨号以确定服务陈旧内容的时间以及将某些内容视为过时所需的时间的最佳设置,但它应该适合您。有关Varnish performance wiki页面的更多信息。

答案 1 :(得分:1)

我建议在网络服务器级别而不是应用程序中缓存

答案 2 :(得分:1)

我最近刚刚做了几件不同的事情,在每种情况下,基本都是相同的 - 在这种情况下,信息可以在使用前预先生成。

  

定期运行PHP作业(可能来自   CRON)生成信息   Memcached,然后使用   可能数百次直到   它再次重建。

尽管它们被缓存了明确定义的时期(无论是60分钟还是1分钟),但它们的再生频率要高于此。因此,除非出现问题,否则它们永远不会从Memcache过期,因为较新的版本会在它们过期之前进行缓存。当然,你可以安排它们永不过期。

我也通过队列完成了类似的事情 - 你可以看到我之前回答的有关'BeanstalkD'的问题。

答案 3 :(得分:0)

根据内容,jQuery.load()可能是一个选项。 (我用它作推特)

第1步
显示Feed的缓存版本。

第2步
通过jQuery.load()更新页面上的内容并缓存结果。


这样页面加载速度很快并显示up2date内容(在x秒之后) 但是,如果重建/加载整页,这将无法提供良好的用户体验。

答案 4 :(得分:0)

您描述了一些问题,也许一些一般性的想法会有所帮助。

一个问题是,您生成的内容太大而无法完全存储,因此您只能缓存该总内容的子集,您将需要:一种唯一标识可生成的每个内容对象的方法,一种用于标识内容对象已经在缓存中,用于标记缓存陈旧中的数据以指示应该运行后台重新生成的策略,以及用于使缓存中的数据到期和替换的策略。最终保持唯一内容标识简单应有助于提高性能,同时应使用对象到期和标记陈旧对象的策略来定义内容对象的后台重新生成的优先级。这些可能是对现有缓存方案的简单更新,另一方面,使用专门用于满足此需求的软件包可能更有效,因为这不是一个不常见的问题。

另一个问题是您不想复制工作以重新生成内容。如果您有多个具有不同功能的并行生成引擎,那么这可能不是一件坏事,最好将任务排队到每个引擎,并在第一个生成器完成作业时从所有其他队列中删除该任务。在重新生成过程中,请考虑跟踪对象状态,以便可以激活多个后台重新生成任务,而无需无意中重复工作。再次,这可以取代现有的缓存系统或由专用的缓存软件包处理。

第三个问题涉及当客户端请求未缓存且需要重新生成的数据时要执行的操作。如果需要完全重新生成数据,您将无法使客户端等待重新生成完成,为了帮助完成长内容生成,您可以确定用于预测预取内容对象到缓存的策略,但需要一种方法来识别内容对象之间的关系。您是否希望为客户提供“重新生成”页面,直到请求的内容可用为止,这取决于您客户的期望。如果无法在10-15秒内完成内容重新生成,请考虑使用压缩数据存档的多级缓存。

充分利用成熟的网络缓存软件包可能会解决所有这些问题。 Nick Gerakines提到了Varnish,它似乎非常适合您的需求。