防止狗堆效應——問題和解決方案
這是Przemek Sobstel 的客座轉貼,他認爲 dogpile 效應問題沒有得到足夠的涵蓋,尤其是在 PHP 世界中。原文: 防止dogpile效應。
當緩存過期並且網站同時受到大量請求時,就會發生 Dogpile 效應。根據我在大流量網站上工作的經驗,這是我認爲最好的最佳解決方案。它在野外成功使用並且有效。許多人提到存儲兩個冗餘值 FRESH + STALE,但對於大流量網站來說,它正在扼殺我們的網絡。我們認爲值得分享我們的解決方案並開始討論以分享經驗。
防止狗堆
在 Web 應用程序中實現緩存似乎很簡單。您檢查值是否被緩存。如果是,則從緩存中獲取緩存值並提供服務。如果不是,則生成新值並將其存儲在緩存中以供將來請求使用。就這麼簡單。
但是,如果值過期然後您收到數百個請求怎麼辦?它不能再從緩存中提供,因此您的數據庫會受到大量試圖重新生成該值的進程的影響。數據庫收到的請求越多,它們的響應速度就越慢。負載尖峯。直到最終他們可能會倒下。
請參見下圖(綠色 - 在緩存中,紅色 - 無緩存)。
防止 dogpile 效應歸結爲只有一個進程(第一個進程)重新生成新值,而其他後續進程從緩存中提供陳舊值,直到它被第一個進程引用。
擔心提供過時的數據?好吧,如果您的數據庫超載和受苦,提供陳舊數據是您可以擁有的最小的不便。如果重新生成新價值需要很長時間,那麼讓多個進程(而不是一個)執行此操作將無濟於事。它只會增加更多的負載。
狗堆效應——預防/實施
使用信號量鎖可以防止 Dogpile 效應。如果值過期,第一個進程獲取鎖並開始生成新值。所有後續請求都會檢查是否已獲取鎖並提供過時的內容。生成新值後,釋放鎖。
需要注意的重要一點是,實際上值應該被賦予延長的生命週期,因此它們在過期時不會被物理移除,並且在需要時仍然可以提供。
這是它的詳細工作原理。
從緩存存儲中獲取緩存值。
$value = $this->store->get($key);
$value
是一個 值對象。
檢查緩存值是否過期。如果沒過期,就上桌。
if ($value && !$value->isStale()) {
return $value->getResult();
}
否則,獲取鎖,這樣只有一個進程重新生成新值。
$lock_acquired = $this->acquireLock($key, $grace_ttl);
如果無法獲取鎖,則意味着已經有其他進程重新生成它,所以我們只提供當前(過時)值。
if (!$lock_acquired) {
return $value->getResult();
}
否則(已獲取鎖),重新生成新值。
$result = ...
將重新生成的值保存在緩存存儲中。添加寬限期,以便在其他進程需要時可以提供陳舊的結果。
$expiration_timestamp = time() + $ttl;
$value = new Value($result, $expiration_timestamp);
$real_ttl = $ttl + $grace_ttl;
$this->store->set($key, $value, $real_ttl);
釋放鎖定。
$this->releaseLock($key);
完整實施: https: //github.com/sobstel/metaphore/blob/master/src/Cache.php。
比喻
Metaphore 是一個開源庫,用於防止 PHP 應用程序中的 dogpile 效應。它實際上是對 LSDCache的重寫,它已成功用於許多高流量生產 Web 應用程序。我只是認爲 LSDCache 已經發展成爲多用途緩存庫,而 metaphore 則力求簡單地只做一件事並將其做好。
用法非常簡單。
在 composer.json 文件中:
"require": {
"sobstel/metaphore": "dev-master"
}
在您的 PHP 文件中:
use Metaphore\Cache;
// initialize $memcached object (new Memcached())
$cache = new Cache($memcached);
$cache->cache($key, function(){
// generate content
}, $ttl);
更多閱讀
- 高可擴展性 - 策略:打破 Memcache Dog Pile
- Memcached - 避免蜂擁而至
- LeaseWeb 實驗室 - 避免內存緩存“狗堆”效應
- mysqlnd-qc 滿貫防禦
- 狗堆效應以及如何使用 Ruby on Rails memcache-client 補丁避免它
- 如何避免 Rails 應用程序中的狗樁效應
- 薄荷緩存
- Varnish Grace 示例
謝謝
感謝 Mariusz Gil 在 2010 年 PHPCon 上關於 Memcached 的演講——這讓我意識到狗堆效應問題——並允許我使用幻燈片中的圖片。