前言
設(shè)計一個緩存系統(tǒng),不得不要考慮的問題就是:緩存穿透、緩存擊穿與失效時的雪崩效應(yīng)。
緩存穿透
緩存穿透是指查詢一個一定不存在的數(shù)據(jù),由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從存儲層查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個不存在的數(shù)據(jù)每次請求都要到存儲層去查詢,失去了緩存的意義。在流量大時,可能DB就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應(yīng)用,這就是漏洞。

解決方案:
-
將這個不存在的key預(yù)先設(shè)定一個值。比如,”key” , “&&”。在返回這個&&值的時候,應(yīng)用層可以認(rèn)為這是不存在的key,應(yīng)用就可以進行相應(yīng)的業(yè)務(wù)操作(繼續(xù)等待、繼續(xù)訪問、放棄操作、...);
標(biāo)識返回
2. 與第一種解決方案類似,只不過存放在緩存當(dāng)中,查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個標(biāo)識(如:&&)結(jié)果進行緩存,但它的過期時間會很短,最長不超過五分鐘,異步進行數(shù)據(jù)庫數(shù)據(jù)讀取,獲取到的值初始化到緩存里邊;

-
采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力;
bitmap過濾
緩存雪崩(很多數(shù)據(jù))
緩存雪崩是指在我們設(shè)置緩存時采用了相同的過期時間,導(dǎo)致緩存在某一時刻同時失效,請求全部轉(zhuǎn)發(fā)到DB,DB瞬時壓力過重雪崩。
解決方案
1. 用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的并發(fā)請求落到底層存儲系統(tǒng)上;
2. 將緩存失效時間分散開,比如我們可以在原有的失效時間基礎(chǔ)上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復(fù)率就會降低,就很難引發(fā)集體失效的事件。
緩存擊穿(單個數(shù)據(jù))
緩存在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的并發(fā)請求過來,這些請求發(fā)現(xiàn)緩存過期一般都會從后端DB加載數(shù)據(jù)并回設(shè)到緩存,這個時候大并發(fā)的請求可能會瞬間把后端DB壓垮。
解決方案:
1.使用互斥鎖(mutex key)
業(yè)界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當(dāng)操作返回成功時,再進行l(wèi)oad db的操作并回設(shè)緩存;否則,就重試整個get緩存的方法。
2. “提前”使用互斥鎖(mutex key)
在value內(nèi)部設(shè)置1個超時值(timeout1), timeout1比實際的memcache timeout(timeout2)小。當(dāng)從cache讀取到timeout1發(fā)現(xiàn)它已經(jīng)過期時候,馬上延長timeout1并重新設(shè)置到cache。然后再從數(shù)據(jù)庫加載數(shù)據(jù)并設(shè)置到cache中。
3. “永遠(yuǎn)不過期”(同數(shù)據(jù)庫的“軟”刪除原理)
這里的“永遠(yuǎn)不過期”包含兩層意思:
(1) 從redis上看,確實沒有設(shè)置過期時間,這就保證了,不會出現(xiàn)熱點key過期問題,也就是“物理”不過期。
(2) 從功能上看,如果不過期,那不就成靜態(tài)的了嗎?所以我們把過期時間存在key對應(yīng)的value里,如果發(fā)現(xiàn)要過期了,通過一個后臺的異步線程進行緩存的構(gòu)建,也就是“邏輯”過期。
從實戰(zhàn)看,這種方法對于性能非常友好,唯一不足的就是構(gòu)建緩存時候,其余線程(非構(gòu)建緩存的線程)可能訪問的是老數(shù)據(jù),但是對于一般的互聯(lián)網(wǎng)功能來說這個還是可以忍受。

4. 資源保護(深入使用第3種,這種沒有深入研究)
采用netflix的hystrix,可以做資源的隔離保護主線程池,如果把這個應(yīng)用到緩存的構(gòu)建也未嘗不可。
總結(jié):沒有最佳只有最合適

針對業(yè)務(wù)系統(tǒng),永遠(yuǎn)都是具體情況具體分析,沒有最好,只有最合適。
轉(zhuǎn)摘與出處:https://blog.csdn.net/zeb_perfect/article/details/54135506

