一、緩存穿透
1.1 定義
緩存穿透是指查詢一個一定不存在的資料,由于緩存是不命中時需要從資料庫查詢,查不到資料則不寫入緩存,這将導緻這個不存在的資料每次請求都要到資料庫去查詢,造成緩存穿透。
1.2 解決
方案一: 緩存空對象
當存儲層未命中後,即使資料庫傳回的空對象也對其進行緩存,同時設定一個過期時間,之後再通路這個資料将會從緩存中擷取,保護了後端資料源。
方案二: 布隆過濾器
布隆過濾器是一種資料結構,對所有可能查詢的參數以hash形式存儲,在控制層進行校驗,不符合則丢棄,進而避免了對底層存儲系統的查詢壓力。
它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識别率和删除困難。
方案三: 設定可通路的白名單
使用bitmaps類型定義一個可以通路的名單,名單id作為bitmaps的偏移量,每次通路和bitmap裡面的id進行比較,如果通路id不在bitmaps裡面,進行攔截,不允許通路。
方案四: 進行實時監控
當發現Redis的命中率開始急速降低,需要排查通路對象和通路的資料,和運維人員配合,可以設定黑名單限制服務
二、緩存擊穿
2.1 定義
key對應的資料存在,但在redis中過期,此時若有大量并發請求過來,這些請求發現緩存過期一般都會從後端DB加載資料并回設到緩存,但是緩存回設期,這個時候大并發的請求可能會瞬間把後端DB壓垮。
案例:微網誌熱搜問題
2.2 解決方案
方案一:預先設定熱門資料
在redis高峰通路之前,把一些熱門資料提前存入到redis裡面,加大這些熱門資料key的時長
方案二:設定熱點資料永不過期
從緩存層面來說,沒有設定過期時間,是以就不會出現熱點key過期産生的問題
方案三:實時調整
現場監控哪些資料熱門,實時調整key的過期時長
方案四:使用分布式鎖
使用分布式鎖,保證對于每個key同時隻有一個線程去查詢後端服務,其他線程在沒有擷取分布式鎖的權限時,需要等待。這種方式将高并發的壓力轉移到了分布式鎖,是以對于分布式鎖的考驗很大。

三、緩存雪崩
3.1 定義
緩存雪崩,是指在某個時間段,緩存集中過期失效,導緻資料庫異常的狀況。
key對應的資料存在,但在redis中過期或者是緩存服務直接當機,此時若有大量并發請求過來,這些請求發現緩存過期一般都會從後端DB加載資料并回設到緩存,這個時候大并發的請求可能會瞬間把後端DB壓垮。
3.2 解決方案
方案一:建構叢集
通過搭建Redis叢集,保障Redis的高可用
方案二:搭建多級緩存架構
Nginx緩存+Redis緩存+其他緩存(ehcache等)
方案三:限流降級
在緩存失效後,通過加鎖或者隊列來控制讀資料庫寫緩存的線程數量,進而避免失效時大量的并發請求落到底層存儲系統上。比如對某個key隻允許一個線程查 詢資料和寫緩存,其他線程等待。
不适用高并發情況。
方案四:資料預熱
在正式部署之前,先把可能的資料先預先通路一遍,這樣部分可能大量通路的資料就會加載到緩存中,
在即将發生大并發通路前手動觸發加載緩存不同的key,設定不同的過期時間,讓緩存失效的時間點盡量均勻
方案五:設定過期标志更新緩存
記錄緩存資料是否過期(設定提前量),如果過期會觸發通知另外的線程在背景去更新實際key的緩存
方案六:将緩存失效時間分散開
比如我們可以在原有的失效時間基礎上增加一個随機值,比如1-5分鐘随機,這樣每一個緩存的過期時間的重複率就會降低,就很難引發集體失效的事件。