狗堆效應 dog-pile

防止狗堆效應——問題和解決方案

這是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);

更多閱讀

謝謝

感謝 Mariusz Gil 在 2010 年 PHPCon 上關於 Memcached 的演講——這讓我意識到狗堆效應問題——並允許我使用幻燈片中的圖片。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章