memcached通常用於在訪問一些性能相對低下的數據接口時(如數據庫),爲了保證這些數據接口的穩定性,加上memcached以減小訪問次數,保證這些數據接口的健壯性。通常memcached的數據都是定時失效的,當數據失效時通常會再次去訪問取數據接口,而後將其更新至memcached中。這時就會有一個問題,當某個數據失效時,剛好同時有大量的客戶端訪問該數據,這時這些客戶端都會發現該數據失效,而後都會去調用數據接口去取數據更新,這天然就瞬間地使數據接口失去了memcached的保護,有可能形成系統的故障。shell
那麼如何解決這個問題呢?數據庫
第一種:數據不失效,定時更新。即數據存放在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代表當前客戶端在更新該數據,當其它客戶端也來訪問時發現失效後就等待直到更新好數據爲目。memcached
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失效之間的一段時間就觸發更新的方式來解決這個問題。性能