首頁  >  文章  >  Java  >  Memcache mutex設計模式

Memcache mutex設計模式

巴扎黑
巴扎黑原創
2016-12-20 13:48:341332瀏覽

場景 
Mutex主要用於有大量並發訪問並存在cache過期的場合,如 

首頁top 10, 由數據庫加載到memcache緩存n分鐘 
微博中名人的content cache, 一旦不存在會大量請求不能命中並且載入資料庫 
需要執行多個IO操作產生的資料存在cache中, 例如查詢db多次 
問題 
在大並發的場合,當cache失效時,大量並發同時取不到cache,會同一瞬間去存取db並回設cache,可能會為系統帶來潛在的超負荷風險。我們曾經在線上系統出現過類似故障。 

解決方法 
方法一 
在load db之前先add一個mutex key, mutex key add成功之後再去做加載db, 如果add失敗則sleep之後重試讀取原cache資料。為了防止死鎖,mutex key也需要設定過期時間。偽代碼如下 
(註:下文偽代碼僅供了解思路,可能有bug,歡迎隨時指出。) 

Java代碼  

if (memcache.get(key) == null) {  
    // 3 min timeout to avoid mutex holder crash  
    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {  
        value = db.get(key);  
        memcache.set(key, value);  
        memcache.delete(key_mutex);  
    } else {  
        sleep(50);  
        retry();  
    }  
}



方法  

v = memcache.get(key);  
if (v == null) {  
    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {  
        value = db.get(key);  
        memcache.set(key, value);  
        memcache.delete(key_mutex);  
    } else {  
        sleep(50);  
        retry();  
    }  
} else {  
    if (v.timeout <= now()) {  
        if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {  
            // extend the timeout for other threads  
            v.timeout += 3 * 60 * 1000;  
            memcache.set(key, v, KEY_TIMEOUT * 2);  
  
            // load the latest value from db  
            v = db.get(key);  
            v.timeout = KEY_TIMEOUT;  
            memcache.set(key, value, KEY_TIMEOUT * 2);  
            memcache.delete(key_mutex);  
        } else {  
            sleep(50);  
            retry();  
        }  
    }  
}


方法 

在valueue timeout1比實際的memcache timeout(timeout2)小。當從cache讀取到timeout1發現它已經過期時候,馬上延長timeout1並重新設定到cache。然後再從資料庫載入資料並設定到cache。偽代碼如下 



Java代碼  
rrreee


相對於方案一 

優點:避免cache失效時刻大量請求獲取不到mutex並進行sleep 

缺點:優點:避免cache失效時刻大量請求獲取不到mutex並進行sleep 
缺點:代碼:複雜性增大方案已經足夠。

🎜方案二在Memcached FAQ中也有詳細介紹How to prevent clobbering updates, stampeding requests,並且Brad還介紹了用他另外一個得意的工具Gearman 來實現單實例設置cache的方法,見Cache miss stampedes,不過用Gearman來解決就感覺就有點奇技淫巧了。 🎜🎜🎜🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn