文章目錄
- 緩存雪崩、擊穿、穿透
- 1.緩存雪崩
- 造成緩存雪崩
- 解決緩存雪崩
- 2. 緩存擊穿
- 造成緩存擊穿
- 解決緩存擊穿
- 3.緩存穿透
- 造成緩存穿透
- 解決緩存穿透
緩存雪崩、擊穿、穿透
一般用戶數據存儲于磁盤,讀寫速度慢。
使用redis作為緩存,相當于數據緩存在內存,大大提高系統性能
redis作為緩存,就會有緩存異常的三個問題
1.緩存雪崩
緩存都設置了過期時間
造成緩存雪崩
-
大量緩存數據在同一時間過期
-
redis故障宕機
若此時有大量用戶請求,無法在redis處理,都直接訪問數據庫 => 數據庫壓力驟增(嚴重造成數據庫宕機) => 形成一系列連鎖反應 => 整個系統崩潰
解決緩存雪崩
=> 大量緩存數據在同一時間過期時:
-
均勻設置過期時間(對緩存數據的過期時間加上隨機數,保證數據不會在同一時間過期)
-
互斥鎖(當業務線程在處理用戶請求時,如果發現訪問的數據不在redis里,加互斥鎖,保證同一時間內只有一個請求來構建緩存(從數據庫讀取數據,再將數據更新到redis),當緩存構建完成后,再釋放鎖。)
注:互斥鎖設置超時時間,否則若出現請求發生意外阻塞,導致其他請求也一直拿不到鎖 -
后臺更新緩存(讓緩存“永久有效”,將更新緩存的工作交由后臺線程定時更新)
當系統內存緊張時,有些緩存數據被“淘汰”,在“淘汰”和下次更新時間內,業務線程讀取失敗就以為是數據丟失,解決方法:-
后臺線程負責定時更新緩存,同時頻繁地檢測緩存是否失效,若失效,可進行構建緩存
? 檢測時間間隔不能太長,太長導致用戶獲取的數據是空值而不是真正的數據,檢測時間間隔最好是毫秒級,用戶體驗一般
-
業務線程發現緩存數據失效后,通過消息隊列發送一條消息通知后臺線程更新緩存。后臺線程收到消息后,更新前判斷緩存是否存在,不存在則進行構建緩存。
? 緩存更新及時,用戶體驗好
**注:**后臺更新緩存機制適合進行緩存預熱(業務剛上線時,提前緩存數據,不是等待用戶訪問才來觸發緩存構建)
-
=> Redis故障宕機時:
-
服務熔斷或請求限流機制
? 服務熔斷:暫停業務應用對緩存服務的訪問,直接返回錯誤,不再繼續訪問數據庫,直到redis恢復正常。
? 請求限流機制:只將少部分請求發送到數據庫進行處理,再多的請求就在入口直接拒絕服務,等到Redis恢復正常 并把緩存預熱完后。
-
構建redis緩存高可靠集群
? 通過主從節點的方式構建,若redis緩存的主節點宕機,從節點可以切換成為主節點,繼續提供緩存服務
2. 緩存擊穿
造成緩存擊穿
被頻繁訪問的熱點數據過期,此時大量的請求訪問該熱點數據,直接訪問數據庫,數據庫很容易被高并發的請求沖垮
緩存擊穿可以認為是緩存雪崩的一個子集(對應于大量緩存數據在同一時間過期)
解決緩存擊穿
- 互斥鎖
- 不給熱點數據設置過期時間,由后臺異步更新緩存 / 在熱點數據準備過期前,提前通知后臺線程更新緩存以及重新設置過期時間
3.緩存穿透
對于緩存雪崩、擊穿,數據仍然在數據庫,一旦緩存恢復相應的數據,就可以減輕數據庫的壓力
而對于緩存穿透:
? 用戶訪問的數據,既不在緩存中,也不在數據庫中,導致請求在訪問緩存時,發現緩存缺失,再去訪問數據庫,發現數據庫也沒有要訪問的數據,沒辦法構建緩存來服務后續請求。當有大量的這樣的請求時,數據庫的壓力驟增
造成緩存穿透
- 業務誤操作,緩存中數據和數據庫數據都被誤刪除
- 黑客惡意攻擊,故意大量訪問某些讀取不存在數據的業務
解決緩存穿透
-
非法請求的限制
判斷請求參數是否含有非法值?請求字段是否存在?
-
緩存空值或默認值
當線上業務發現緩存穿透時,針對查詢的數據,在緩存中設置一個空值或默認值,后續請求可以從緩存中讀取到數據,而不會繼續查詢數據庫
-
使用布隆過濾器快速判斷數據是否存在,避免通過查詢數據庫來判斷數據是否存在。
寫入數據庫數據時,使用布隆過濾器做標記,當業務線程確認緩存失效后,可以通過查詢布隆過濾器判斷數據是否存在。(大量請求只會查詢布隆過濾器和redis,而不會查詢數據庫)
注:布隆過濾器的實現
設此時有3個哈希函數,位圖數組長度為8,數據庫寫入數據x:
將該數據x得到的三個哈希值 % 位圖數據長度得到三個數組下標,填入1。
當業務線程查詢數據是否存在于數據庫時,查詢 1、4、6下標的值是否為1,若有一個為0,則說明不存在
(存在哈希沖突,故若查詢布隆過濾器說數據存在于數據庫,此時數據不一定在數據庫;但是查詢到數據不存在時,數據一定不存在)
小林coding圖解Redis — 七