問題描述

我們假設有一個外掛,顯示 20 個相關的帖子 (每個帖子) 與一個非常複雜的查詢。然後使用此查詢中的資料,它構建複雜的 HTML 佈局。另外,應該注意的是,該外掛是公共的,可以安裝在任何配置的任何伺服器上。

就像是:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = '';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */
     $html_output .= ...;
}

所以我的問題是:

  • 快取這些資料最安全和最正確的方法是什麼?

  • 應該使用 Transient API 快取 $related_posts 陣列,還是 $html_output 字串?如果我會快取 $html_ouput 字串,它會達到一些 max-size 限制嗎?我應該可以 gzip 它,然後儲存?

  • 我應該在這裡使用 Transient API 嗎?

最佳解決方案

Should I use Transient API at all here?

沒有。

在一個庫存 WordPress 安裝瞬態儲存在 wp_options 表中,只有在核心升級期間才被清理。假設你有 50,000 個帖子,在選項表中有 5 萬個附加行。顯然,它們設定為 autoload = no,所以它不會消​​耗你所有的 memory ,但還有一個警告。

選項表中的自動載入欄位沒有索引,這意味著對 wp_load_alloptions()的呼叫將執行全表掃描。你擁有的行越多,需要的時間越長。寫入選項表的次數越多,MySQL 內部快取效率越低。

如果快取的資料與帖子直接相關,那麼最好將其儲存在後期後設資料中。這也將在您每次顯示快取的內容時儲存一個查詢,因為在 WP_Query 中的後檢索期間,通常會傳送快取 (通常) 。

您的資料結構的元值可能會有所不同,如果快取的值過時,那麼您可以擁有時間戳並執行昂貴的查詢,就像一個暫時的行為一樣。

另一個重要的想法是記住,WordPress 瞬態可以在具有永續性物件快取的環境中變化。這意味著如果您將快取的資料儲存在短暫的 24 小時內,絕對不保證它將在 23 小時或 12 個甚至 5 分鐘內可用。許多安裝的物件快取後端是 in-memory key-value 儲存,如 Redis 或 Memcached,如果沒有足夠的分配記憶體來適應較新的物件,較舊的專案將被逐出。這是元儲存方法的巨大勝利。

無效也可以更聰明,即為什麼在 X 小時內無效相關的帖子快取?是因為有些內容有所改變嗎?新增了一個新帖子?已分配一個新標籤?根據您的 「複雜和大查詢」,您可以選擇僅在發生改變查詢結果的事情時才使其無效。

Should I use Transient API to cache $related_posts array, or $html_output string? If I’ll cache $html_ouput string, will it reach some max-size limit? Should I maybe gzip it, before saving?

這取決於您的字串的大小,因為這將是 PHP,MySQL 等之間的資料。您需要努力達到 MySQL 的限制,但例如 Memcached 預設的 per-object 限制只有 1 MB 。

您的 「複雜佈局渲染邏輯」 實際需要多長時間?透過分析器執行它來查詢。有可能是非常快速的將永遠不會成為瓶頸。

如果是這樣,我建議快取帖子 ID 。不是 WP_Post 物件,因為那些將包含完整的帖子內容,而只是一個陣列的帖子 ID 。然後只需使用 WP_Querypost__in,這將導致透過主鍵快速的 MySQL 查詢。

也就是說,如果每個專案所需的資料相當簡單,那麼您可以只儲存這三個資料,而不需要額外的 round-trip 到 MySQL 的開銷,並且沒有快取非常長的 HTML 字串的開銷。

哇這是很多話,希望有所幫助。

次佳解決方案

不是所有的 WP 程式碼都是公共程式碼

如果你要釋出公開的東西,那麼 kovshenin 所說的一切都是完全有效的。

如果您要為自己或您的公司編寫私人密碼,情況會有所不同。

外部物件快取是一個很大的好處,在任何情況下

設定外部持久物件快取是非常推薦的,可以的時候。

所有關於 kovshenin 關於瞬態和 MySQL 的答案都是非常真實的,考慮到 WP 本身和一堆外掛使用物件快取… 然後效能提升,絕對值得 (小) 努力設定像 Redis 或 Memcached 這樣的現代快取系統。

快取值可能不在那裡:沒關係

而且,是的,外部物件快取是不可靠的。你不應該依賴於一個瞬間的事實。如果快取不在其中,則需要確保它有效。

快取是 notstorage,快取是快取。

選擇使用快取

看這個例子:

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined('WP_DEBUG') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters('my_use_cache', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}

使用這樣的程式碼,在您的私人網站中,網站效能可以提高很多,特別是如果您有很多使用者。

注意:

  • 預設情況下,除錯開啟時不使用快取,因此希望在您的開發環境中。相信我,快取可以讓除錯成為一個地獄

  • 預設情況下,當 WP 未設定為使用外部物件快取時,快取也不會被使用。這意味著與 MySQL 連線的所有問題都不存在,因為當 MySQL 使用 MySQL 時,不會出現任何瞬態問題。使用 wp_cache_*功能可能更容易一些,所以如果沒有設定外部快取,那麼快取就會在記憶體中發生,資料庫永遠都不會涉及。

  • 快取的使用是可過濾的,可以處理您可能遇到的一些邊情況

沒有 Webscale 如果沒有快取

您不應該嘗試解決快取的速度問題。如果你有速度問題,那麼你應該 re-think 你的程式碼。

但是,要在 webscale 上擴充套件一個網站,快取是非常需要的。

而且很多次 (但不總是) 片段,context-aware 快取比攻擊性全頁快取更靈活和合適。

你的問題:

Should I use Transient API at all here?

這取決於。

您的程式碼是否耗用大量資源?如果沒有,也可能不需要快取。如上所述,不僅僅是速度的問題。如果你的程式碼執行速度很快,但是對於幾個使用者來說,它需要一堆 CPU 和記憶體?當你有 100 或 1000 個併發使用者時會發生什麼?

如果你認識快取會是個好主意..

… 是公共程式碼:大概沒有。您可以考慮快取快取,就像上面在公共程式碼中的示例一樣,但是如果您對實現者做出這樣的決定,通常會更好。

… 是私人密碼:很可能是的。但即使是私人程式碼,選擇性快取仍然是一件好事,例如除錯。

記住,無論如何,wp_cache_*功能可以讓您訪問快取,而不會有資料庫汙染的風險。

Should I use Transient API to cache $related_posts array, or $html_output string?

這取決於很多事情。字串有多大?你使用哪個外部快取?如果要快取帖子,將 ID 儲存為陣列可能是一個好主意,透過其 ID 來查詢適當數量的帖子是相當快的。

最終註解

瞬態 API 可能是 WordPress 最好的之一。感謝您可以為任何型別的快取系統找到的外掛,它將成為可以在引擎蓋下工作的大量軟體的一個愚蠢的簡單 API 。

在 WordPress 外部,這種使用一堆不同的快取系統開箱即用的抽象,並且允許您從一個系統切換到另一個系統,而不用努力就很難找到。

你很少聽到我說 WordPress 比其他現代的東西更好,但是當我不使用 WordPress 時,瞬態 API 是我想念的幾件事之一。

當然快取很難,不解決程式碼問題,而不是一個銀彈,但是你需要構建一個可以工作的 high-traffic 站點。

使用 under-optimized MySQL 表進行快取的 WordPress 想法是非常瘋狂的,但是不要因為 WordPress 預設情況下使其遠離快取記憶體。

你只需要瞭解事情的運作方式,然後做出選擇。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。