优化缓存结果列表的方式?

时间:2017-02-16 21:24:03

标签: php laravel caching optimization redis

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

我正在处理显示结果的应用(来自用户启动的搜索或类别列表)。默认情况下,我们为每页分页30个结果。

我使用Redis缓存所有结果,但我遇到了一些优化问题。首先,我使用完全存储在结果集中的对象(Products)缓存整个结果集(因此基本上每个结果列表都是30个数据对象的一个​​巨型缓存条目)。这很好,但内存使用量飙升,因为对象存储在多个不同的缓存对象中(产品可能出现在多个搜索结果和类别中 - 然后默认情况下每个对象都会单独缓存)。

另外,另一个问题是,由于我们允许不同的分页,我们也必须缓存其他对象数。

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

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

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

1 个答案:

答案 0 :(得分:0)

  

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

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

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

HTML不需要序列化,这种方法应该非常有效。

您甚至可以通过AJAX执行此操作:对象是"预渲染"作为一个适当大小的AJAX占位符"请等待"动画

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

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

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