緩存擊穿
假設一個緩存系統中存在一個熱Key,每分每秒都有大量的請求訪問這個key,那麼當這個熱key由於過時而失效,一瞬間全部的請求直接打到DB上,這種場景稱作緩存擊穿。html
爲了不這種問題業界通常有以下解決方案緩存
1.互斥鎖
當緩存過時時,常見的邏輯是直接請求DB,而後再set回緩存中。爲了不緩存擊穿的問題,能夠在請求DB的地方加一個鎖(若是是分佈式系統就須要使用分佈式鎖),爭取到鎖的就去訪問DB,沒爭取到的就阻塞一段時間再請求緩存,減小直接打到DB的請求。異步
2.永不過時
不給key設置有效期,讓key永不過時,而後以定時任務的形式,主動去更新緩存。分佈式
3.邏輯過時
一樣不給key設置有效期,而是將expired值做爲緩存數據的一個字段放入緩存中,取出來時校驗一下是否過時,若是過時了則從新設置有效期,並起一個異步線程去更新這緩存。spa
緩存雪崩
假設一個緩存系統中,大量的key用的都是同一個expired值,那麼在某一瞬間,這些key可能會集體所有失效,全部的請求直接打到DB上,這種場景稱做緩存雪崩。線程
如何解決?code
1.隨機過時時間
將數據寫入緩存時每每會設置一個expired值,爲了不在某一時間通通所有過時,能夠在expired值的基礎上加上1~5min的隨機值,避免這種狀況。這樣緩存就不會在某一瞬間忽然所有過時了。htm
緩存穿透
當用戶訪問一個不存在的key時,緩存取不到,按邏輯就是從庫裏面取,這種請求一多,打到DB的請求也就增長了,這種場景稱做緩存擊穿。blog
以下,用戶不斷請求用戶信息,但ID都爲無效的負數,緩存裏面沒有,全部請求可能直接打到DB上,若是是惡意請求的話,危害頗大。接口
GET /user/-1 GET /user/-2 .... GET /user/-3
1.緩存不存在的值
若是查詢到一個空的結果時,能夠仍然將這個空的結果進行緩存,下次在請求的話就會這就返回這個空的結果而不是請求DB。固然,若是這種請求一多,存儲裏就會存儲大量這種無效值,對緩存的空間也是一種壓力,因此推薦使用下面BloomFilter的方式。
2.BloomFilter
BloomFilter的特性就是當BloomFilter認爲有數據時,是可能有,當認爲沒有數據時,那就是真沒有。故能夠利用BloomFilter的特性,擋掉這些不存在的請求。
緩存預熱
系統剛啓動,緩存還未徹底構建,可是用戶不會管這麼多,直接一股腦的訪問過來,請求又直接打到DB了。若是遇到這種場景,能夠利用緩存預熱的思想,在系統啓動時調用一個後臺接口,構建一遍緩存。
原文出處:https://www.cnblogs.com/fudashi233/p/10706750.html