2017-02-16 35 views
0

這是一個針對PHP/Laravel + Redis的問題,但我確定它可以外推到其他語言/框架。優化的方式來緩存結果列表?

我正在研究一個顯示結果的應用程序(來自用戶發起的搜索或類別列表)。默認情況下,我們爲每頁分頁30個結果。

我使用Redis來緩存所有的結果,但我遇到了幾個優化問題。起初,我使用完全存儲在結果集中的對象(Products)來緩存整個結果集(因此基本上每個結果列表都是一個包含30個數據對象的巨大緩存條目)。這很好,但由於對象存儲在多個不同的緩存對象(產品可能出現在多個搜索結果以及類別中 - 然後每個對象將被默認單獨緩存),所以內存使用量激增。另外,另一個問題是,由於我們在不同的計數中允許不同的分頁,所以我們也必須緩存其他的對象計數。

那麼接下來我嘗試緩存每個頁面的對象標識列表。這大大減少了內存使用量,但每次加載頁面時,我們都必須遍歷30個對象並從緩存中檢索它們,然後重新創建它們。在每個對象大約50毫秒(這看起來很高)時,頁面加載可以累計高達1.5秒。即使我們進一步優化了對象的創建,它仍然是一個添加到頁面加載/渲染的具體時間。我們的下一個嘗試是HTML緩存(Cloudflare/Varnish等),這將要求我們重新設計應用程序的某些方面,這很好。然而,對我來說,我想知道沒有HTML緩存是他們優化這種方式的方式(或者我們正在做什麼的最佳方法是什麼?)。另外,我遇​​到的另一個問題是,當我知道每個請求都執行PHP腳本時,爲什麼我們不能將執行之間的對象作爲POPO(Plain Old PHP Objects)來維護?在這一點上,我似乎很愚蠢,我們仍然在2017年序列化和反序列化對象。我很想擁有一個後臺PHP應用程序,它維護所需的對象,並能夠根據需要將它們傳遞給每個腳本。

例如,從頁面加載到頁面加載,產品的變化不會很大。爲什麼每分鐘重新創建相同的產品對象數百次 - 即使它來自緩存?

+0

愚蠢的問題警報,但在你的第二次嘗試中,你爲什麼要遍歷對象而不是一次全部獲取它們?聽起來像你的描述會節省你很多時間。值得一提的另一個解決方案是將數據轉換爲您實際需要的數據,並僅將其存儲在緩存中,而不是整個對象。你可以很容易地用例如分形。 –

回答

0

我很想擁有一個後臺PHP應用程序,它維護所需的對象,並且能夠根據需要將它們傳遞給每個腳本。

你不能這麼做,因爲單獨的應用程序不共享範圍(它們甚至不共享內存)。所以你的後臺應用需要以某種中間形式傳遞對象。是的,你猜對了。序列化。

可以做什麼是分開一些服務或HTML生成的部分,使他們只與一個特定的對象完全關聯。那時你可能會有一個運行Object Brokering的後臺應用程序。通過使用對象ID調用代理並詢問其HTML,代理可以緩存對象或呈現的HTML,具體取決於最佳方式。

不需要序列化的HTML,這個方法應該是相當高效的。

你甚至可以通過AJAX來做到這一點:一個對象是「預渲染」作爲一個AJAX佔位符適當的大小和「請稍候」動畫

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

,然後一系列平行的jQuery調用對象的動畫。

我做到了這一點(對於分頁thingy,去圖),並獲得了非常好的結果與瘋狂的動畫,開始作爲一個焦點(當然沒有騎自行車)的焦點非常集中搜索結果。這發生得非常緩慢,同時AJAX呼叫得到解決,並且真實對象被混合在一起。對象非常相似,您很少發現未聚焦圖像和最終對象實際上沒有關聯,並且用戶平均沒有沒有注意到前兩三個物體還沒有渲染 - 他看到整個結果頁面立即出現,並認爲所有結果都在那裏。這些對象也在本地緩存,所以來回翻頁不會給服務器帶來不止一次的壓力。