【问题标题】:Optimized way to cache a list of results?缓存结果列表的优化方法?
【发布时间】:2017-07-06 05:05:46
【问题描述】:

这是 PHP/Laravel + Redis 的问题,但我确信它可以外推到其他语言/框架。

我正在开发一个显示结果的应用程序(来自用户发起的搜索或类别列表)。默认情况下,我们每页分页 30 个结果。

我使用 Redis 来缓存所有结果,但我遇到了一些优化问题。起初,我使用完全存储在结果集中的对象(产品)来缓存整个结果集(所以基本上每个结果列表都是一个包含 30 个数据对象的巨大缓存条目)。这很好,但是随着对象存储在多个不同的缓存对象中(一个产品可能出现在多个搜索结果和类别中——然后每个对象默认单独缓存),内存使用量激增。

另外,另一个问题是,由于我们允许以不同的计数进行不同的分页,因此我们也必须在其他对象计数时进行缓存。

那么我接下来尝试的只是缓存每个页面的对象 ID 列表。这显着减少了内存使用量,但是每次加载页面时,我们都必须遍历 30 个对象并从缓存中检索它们,然后重新创建它们。每个对象大约 50 毫秒(这似乎很高),它最多可以增加 1.5 秒来加载页面。即使我们进一步优化对象的创建,仍然会增加页面加载/渲染的具体时间。

我们的下一个尝试是 HTML 缓存(Cloudflare/Varnish 等),这将要求我们重新设计应用程序的某些方面,这很好。但是,对我来说,我想知道没有 HTML 缓存是他们优化这一点的方法(或者什么是我们正在尝试做的最佳方法?)。此外,我遇到的另一个问题是,虽然我知道 PHP 脚本在每个请求时都会执行,但为什么我们不能在执行之间将对象维护为 POPO(普通旧 PHP 对象)?在这一点上,我觉得在 2017 年我们仍在序列化和反序列化对象似乎很愚蠢。我希望有一个后台 PHP 应用程序来维护所需的对象并能够根据需要将它们传递给每个脚本。

例如,产品从页面加载到页面加载不会有太大变化。为什么每分钟重新创建数百次相同的 Product 对象——即使它来自缓存?

【问题讨论】:

  • 愚蠢的问题警报,但是在您的第二次尝试中,您为什么要遍历对象而不是一次获取所有对象?从你的描述来看,这样可以为你节省很多时间。另一个值得一提的解决方案是将数据转换为您实际需要的数据,并将其仅存储在缓存中,而不是整个对象。您可以通过例如轻松实现这一目标分形。

标签: php laravel caching optimization redis


【解决方案1】:

我希望有一个后台 PHP 应用程序来维护所需的对象并能够根据需要将它们传递给每个脚本。

您不能这样做,因为单独的应用程序不共享范围(它们甚至不共享内存)。因此,您的后台应用程序需要以某种中间形式传递对象。是的,你猜对了。序列化。

可以做的是分离一些服务或 HTML 生成的部分,以便它们完全与特定对象相关联。此时,您可能能够拥有一个运行对象代理的后台应用程序。通过使用对象 ID 调用代理并请求其 HTML 来呈现对象,代理可以根据最佳情况缓存对象或呈现的 HTML。

HTML不需要序列化,这个方法应该很高效。

您甚至可以通过 AJAX 做到这一点:一个对象被“预渲染”为具有适当大小和“请稍候”动画的 AJAX 占位符

<div class="Placeholder Product"></div>

然后一系列并行的 jQuery 调用为对象设置动画。

我这样做了(对于一个分页的东西,去看看)并通过一个疯狂的动画获得了非常好的结果,该动画开始是一个非常没有焦点的搜索结果,逐渐成为焦点(当然没有循环)。这发生得太慢了,同时 AJAX 调用得到了解决,并且真实的对象被混合了。对象非常相似,以至于你很少发现未聚焦的图像和最终对象实际上并不相关,并且用户平均没有'没有注意到前两个或三个之后的对象还没有渲染 - 他看到整个结果页面立即出现并认为所有结果都在那里。对象也在本地缓存,因此来回分页不会对服务器造成多次压力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多