为啥 Magento 在产品保存时使整页缓存失效实际上使页面未缓存以及由于未缓存而刷新会做啥

Posted

技术标签:

【中文标题】为啥 Magento 在产品保存时使整页缓存失效实际上使页面未缓存以及由于未缓存而刷新会做啥【英文标题】:Why Does Magento Invalidation of Full Page Caching on Product save actually make a page not cached and what does refresh do since it is not cached为什么 Magento 在产品保存时使整页缓存失效实际上使页面未缓存以及由于未缓存而刷新会做什么 【发布时间】:2012-06-14 19:58:01 【问题描述】:

所以缓存当然是 Magento 中最让我困惑的地方,我相信它对大多数其他人也是如此。目前我们工作的网站之一是企业网站,当然也使用 FPC。问题是,我们有一个每 15 分钟运行一次的库存更新。很多订单都是通过电话向 CSR 下达的,并通过目录进入 Magento 之外的外部系统。

每 15 分钟运行一次脚本以检查该系统中的所有库存,并查看它是否与 Magento 中的不同。如果存在差异,则在 Magento 中更新库存。使用所有 Magento 方法,没有 sql 或类似的东西。

我们一直遇到缓存问题,并且在所有最新技术问世时都尝试过。我们正在尝试的最新一个是 Redis,我们在其他网站上已经取得了很好的成功。然而,我们仍然在服务器上看到了疯狂的负载,很明显页面没有被缓存。

在深入研究代码后,似乎每次保存模型或管理产品控制器后,它都会查看是否需要使缓存失效。看来更改任何属性,至少库存都会将 FPC 标记为需要失效。

我对失效的含义感到困惑,因为不久前我们向客户支持提出了一个关于类似问题的问题,这就是回复

整页缓存将到达 产品、类别、CMS 发生任何更改时的无效状态 即使在销售后库存减少。

现在,当整页缓存进入无效状态时,这并不意味着 您的前端发生了某些更改,但是应用了任何更改 最后一次刷新后不会显示在前端。

但是,如果您必须始终验证 FPC 您当然可以将 Magento 安装设置为业务逻辑 经常通过 cron 功能自动刷新它 渴望。

但是,在我所做的所有测试中,无论是在 1.9 还是 1.11 Enterprise 上,当 FPC 失效时都会出现,响应没有从缓存中拉入。这与他们所说的只是没有更新的更新相矛盾。

我有什么遗漏吗?有没有人很好地解释了 Magento 中的失效是如何专门针对 FPC 工作的,或者有任何好的链接可以完全理解流程和代码?

您可以自己尝试对任何全页缓存的页面进行此操作。但据我了解,/app/code/core/Mage/Core/Model/Cache.php 中的方法 processRequest 应该使用缓存的响应设置正文内容,如果页面被缓存,则返回 true。

要测试转到任何页面,请确保您已将其缓存并返回 true。进入并编辑产品,在我们的例子中是数量。这将使 FPC 无效。但是,现在当您加载之前缓存的页面时,它将在此方法中返回 false 并且不是缓存页面。我不知道这是否准确能够判断页面是否被缓存,但这就是我的调查引导我的地方。如果我错了,请纠正我。

更新: 经过进一步调查,我发现当您在管理员中保存产品时,控制器操作

Mage_Adminhtml_Catalog_ProductController::saveAction()

会调用下面的方法

Mage::getModel('catalogrule/rule')->applyAllRulesToProduct($productId)

然后在Mage_CatalogRule_Model_Resource_Rule 类中,调用applyAllRulesForDateRange 方法并触发事件

catalogrule_after_apply

全页缓存模块正在观察并触发 FPC 标记的清理缓存方法。实质上是删除所有 FPC 缓存记录。

如果在此之前逻辑是清除与产品和类别标签相关的 FPC 记录,我不明白为什么有必要这样做。这是一个错误吗?

【问题讨论】:

我知道这并不能直接回答您的问题,但我只想指出,您的表现不应该比所有订单都通过 Magento 下达更差,因为每次销售后您的库存会减少,从而使您的缓存失效,就像您的 cron 作业一样。 没错,我明白你的意思。那么它只是没有任何意义,为什么页面在第一次失效时实际上没有被缓存。 这不是您想要的答案,但我已经与其他 Magento 开发人员交谈过,我们中没有一个人在股票 FPC 方面取得了真正的成功。它只会给我们带来麻烦。通常,我们最终会使用 Varnish 或其他一些反向代理缓存。将其与已经足够复杂的内部分开。 是的,我们通过使用 nginx 缓存在另一个客户端站点上做了类似的事情。我们也在研究 Varnish,但非常有信心 Redis 的实现会非常有用 +1 用于 Varnish,我们使用它在许多网站上取得了巨大成功。 Phoenix Varnishcache 扩展通过处理缓存头、产品保存失效等使使用 Varnish 变得更加容易。 【参考方案1】:

FPC 正在观察库存变化,因为其目的是显示所有已减至零库存的产品缺货。解决方法是在产品达到零时而不是每次任何产品更换库存时创建事件调度,并重写 FPC 以观察该事件而不是原始事件。

另一种方法是仅使与正在更新的产品相关的缓存部分无效,但这将是一个相当重要的架构更改。

【讨论】:

【参考方案2】:

您将创建一个新的自定义索引器 Mage_Index_Model_Indexer_Abstract ,并使用 cron 作业创建新的资源模型 api 方法

【讨论】:

【参考方案3】:

phoenix 页面缓存模块清除产品页面和类别页面,但未发现某些缓存失效区域。它也不能很好地处理动态内容。

也许您应该查看 aoe_static 模块,该模块通过加载默认布局并使用 ajax 调用渲染块,在加载动态内容方面做得很好。此 ajax 调用还将 cookie 设置为允许会话。

在相当困难的区域使用 2 个模块时要小心,也许你应该看看这个magento open source full page cache

【讨论】:

【参考方案4】:

阅读我在 Magento 中的整页缓存中写的文章。它突出显示了一个错误修复,它突然使整个缓存机制变得有意义!

http://www.excitedcroc.com/article/why-the-magento-full-page-cache-doesnt-expire

Magento 使用 Zend Framework 缓存机制的方式基本上存在一个错误。

问题在于 Zend 库缓存类和 Magento 企业缓存类在它们的函数中使用了 null 和 false 的混合,这会产生生命周期值。因为 null !== false 总是使用 10 天的默认生命周期。问题源于 app/code/core/Enterprise/PageCache/Model/Processor.php 中的 processRequestResponse 函数。因为保存时没有将生命周期值传递给缓存实例,所以它默认为 null。

更改 app/code/core/Mage/Core/Model/Cache.php 的保存函数的生命周期参数的默认值将解决此问题。只需将其设置为 false 而不是 null (上面链接的文章充分解释了原因)。

- 公共函数保存($data, $id, $tags = array(), $lifeTime = null)

+ 公共函数保存($data, $id, $tags = array(), $lifeTime = false)

【讨论】:

单独的链接被认为是一个糟糕的答案(请参阅faq),因为它本身没有意义,并且不能保证目标资源在未来仍然存在。 It would be preferable 在这里包含答案的基本部分,并提供链接以供参考。 你说的很有价值,但与问题完全无关

以上是关于为啥 Magento 在产品保存时使整页缓存失效实际上使页面未缓存以及由于未缓存而刷新会做啥的主要内容,如果未能解决你的问题,请参考以下文章

Magento Magmi 导入和缓存问题

在多种货币之间切换时,Magento Enterprise 整页缓存(FPC)购物车侧边栏问题

Magento EE 1.9 的缓存:我们应该使用整页缓存(带有打孔)和/或“经典”块缓存吗?

Magento 可以在缓存键中使用会话变量吗?

如何以及通过哪个文件将新产品保存在 Magento 数据库中?

Magento 布局缓存正在保存错误的模板名称