memcached快取失效時的高併發訪問問題解決
阿新 • • 發佈:2019-02-06
memcached一般用於在訪問一些效能相對低下的資料介面時(如資料庫),為了保證這些資料介面的穩定性,加上memcached以減少訪問次數,保證這些資料介面的健壯性。一般memcached的資料都是定時失效的,當資料失效時一般會再次去訪問取資料介面,然後將其更新至memcached中。這時就會有一個問題,當某個資料失效時,恰好同時有大量的客戶端訪問該資料,這時這些客戶端都會發現該資料失效,然後都會去呼叫資料介面去取資料更新,這自然就瞬間地使資料介面失去了memcached的保護,有可能造成系統的故障。
那麼如何解決這個問題呢?
第一種:資料不失效,定時更新。即資料存放在memcached中永不失效,但是會有一個定時任務,定時的去更新這個資料。
第二種:既然該問題的癥結在於在資料失效時,會有多個客戶端去呼叫資料介面,那麼只要想辦法在資料失效時只有一個客戶端能訪問資料介面即可,要做到這點,自然的想法是加鎖:如下:
[java] view plaincopyprint?- 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表明當前客戶端在更新該資料,當其它客戶端也來訪問時發現失效後就等待直到更新好資料為目。
[java]- 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;
上述的方法存在的缺陷時,一旦資料失效,所有客戶端要等待某個客戶端更新完畢,這樣勢必增加伺服器壓力,可以通過在key失效之間的一段時間就觸發更新的方式來解決這個問題。