快取雪崩、快取穿透、快取擊穿
一、快取擊穿(針對某一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 “”,但它的過期時間會很短,最長不超過五分鐘。