1. 程式人生 > >快取雪崩、快取穿透、快取擊穿

快取雪崩、快取穿透、快取擊穿

一、快取擊穿(針對某一key快取)

1.概念

針對於一些設定了過期時間的key,當快取key在某個時間點過期,恰好此時有大量的併發請求進來,發現快取過期時,就會從後端DB載入資料並回設到快取,這個時候大併發的請求可能會瞬間把後端DB壓垮。

2.使用互斥鎖(mutex key)

簡單地來說,就是在快取失效的時候(判斷拿出來的值為空),不是立即去load db。比如Redis使用SETNX去set一個mutex key,當操作返回成功時,再進行load db的操作並回設快取;否則,就重試整個get快取的方法。

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表快取值過期
          //設定3min的超時,防止del操作失敗的時候,下次快取過期一直不能load db
		  if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表設定成功
                      value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
              } else { 
          //這個時候代表同時候的其他執行緒已經load db並回設到快取了,這時候重試獲取快取值即可
                      sleep(50);
                      get(key);  //重試
              }
          } else {
              return value;      
          }
 }

3.提前"使用互斥鎖(mutex key)

當從cache讀取到timeout1發現它已經過期時候,馬上延長timeout1並重新設定到cache。

4.永遠不過期

(1)可以把過期時間存在key對應的value裡,如果發現要過期了,通過一個後臺的非同步執行緒進行快取的構建。唯一不足的就是構建快取時候,其餘執行緒(非構建快取的執行緒)可能訪問的是老資料。

5. 使用netflix的hystrix進行資源保護

如何能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,這個就是Hystrix需要做的事情。Hystrix提供了熔斷、隔離、Fallback、cache、監控等功能

,能夠在一個、或多個依賴同時出現問題時保證系統依然可用。

二、快取雪崩(針對很多key)

1.設定快取時採用了相同的過期時間,導致快取在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。

2.解決方案

(1)將快取時間分散開,比如在原有失效時間的基礎上增加一個隨機值,降低同時失效的重複率。

(2)事前:redis高可用,主從+哨兵,redis cluster,避免全盤崩潰

         事中:本地ehcache快取 + hystrix限流&降級,避免MySQL被打死

         事後:redis持久化,快速恢復快取資料

三、快取穿透

1.快取穿透是指查詢一個一定不存在的資料,如果儲存層查不到資料就不寫入快取,就會向DB請求,流量大時就容易掛掉。利用不存在的key頻繁攻擊我們的應用,這就是漏洞。

2.解決方案

(1)採用布隆過濾器,將所有可能存在的資料雜湊到一個足夠大的bitmap中,一個一定不存在的資料會被 這個bitmap攔截掉;

(2)查詢不到的資料也放到快取,value為空,如set -999 “”,但它的過期時間會很短,最長不超過五分鐘。