memcached緩存失效時的高併發訪問問題解決

memcached通常用於在訪問一些性能相對低下的數據接口時(如數據庫),爲了保證這些數據接口的穩定性,加上memcached以減小訪問次數,保證這些數據接口的健壯性。通常memcached的數據都是定時失效的,當數據失效時通常會再次去訪問取數據接口,而後將其更新至memcached中。這時就會有一個問題,當某個數據失效時,剛好同時有大量的客戶端訪問該數據,這時這些客戶端都會發現該數據失效,而後都會去調用數據接口去取數據更新,這天然就瞬間地使數據接口失去了memcached的保護,有可能形成系統的故障。 php

        那麼如何解決這個問題呢? java

        第一種:數據不失效,定時更新。即數據存放在memcached中永不失效,可是會有一個定時任務,定時的去更新這個數據。 數據庫

        第二種:既然該問題的癥結在於在數據失效時,會有多個客戶端去調用數據接口,那麼只要想辦法在數據失效時只有一個客戶端能訪問數據接口便可,要作到這點,天然的想法是加鎖:以下: 安全

object value = memcached.get(key);  
if(null==value){  
    synchronized{  
        value = memcached.get(key);  
        if(null==value){  
            value = db.get(key);  
            memcached.set(key,value);  
        }  
    }  
}  
return value;
這樣作的前提是你必須保證這個函數的類是單例的,顯然在服務器集羣中不可能有這樣的場景,那麼若是在羣集間加鎖呢?解鈴還需繫鈴人,既然你們共用一個memcached服務器,那麼就使用memcached來實現這個鎖機制。即當客戶端取不到數據時,先在  memcached  中設置一個flag代表當前客戶端在更新該數據,當其它客戶端也來訪問時發現失效後就等待直到更新好數據爲目。
object value = memcahced.get(key);  
if(null=value){  
    if(memcached.add(key)){  
        value = db.get();  
        memcached.set(key,value);  
    }else{  
        while(true){  
            Thread.sleep(50);  
             value=memcached.get(key);  
             if(null!=value){  
                  break;  
             }  
        }  
    }  
}  
return value;
memcached中的add方法是實現該功能的關鍵,該方法是判斷memcached中是否有某個key存在,若是存在則返回false,不然返回true,並添加該key值,若是沒有該方法,顯然咱們只能再一次的經過get 和set去設置該值,顯然這樣作是線程不安全的,有可能有多個客戶端同時取爲空,同時去取數據並更新。

    上述的方法存在的缺陷時,一旦數據失效,全部客戶端要等待某個客戶端更新完畢,這樣勢必增長服務器壓力,能夠經過在key失效之間的一段時間就觸發更新的方式來解決這個問題。 服務器

相關文章
相關標籤/搜索