memcache 緩存失效問題(轉)


在大並發的場合,當cache失效時,大量並發同時取不到cache,會同一瞬間去訪問db並回設cache,可能會給系統帶來潛在的超負荷風險。

解決方法

方法一 
在load db之前先add一個mutex key, mutex key add成功之后再去做加載db, 如果add失敗則sleep之后重試讀取原cache數據。為了防止死鎖,mutex key也需要設置過期時間。偽代碼如下

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();
    }
} 方法二 在value內部設置1個超時值(timeout1), timeout1比實際的memcache 
timeout(timeout2)小。當從cache讀取到timeout1發現它已經過期時候,馬上延長timeout1並重新設置到cache。然
后再從數據庫加載數據並設置到cache中。偽代碼如下

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();
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM