緩存穿透、緩存擊穿、緩存雪崩及其解決方案


前言:緩存的使用場景

緩存的使用場景
設計一個緩存系統,不得不要考慮的問題就是:緩存穿透、緩存擊穿與失效時的雪崩效應。
1.緩存穿透
  緩存穿透是指查詢一個一定不存在的數據,因為緩存中也無該數據的信息,則會直接去數據庫層進行查詢,從系統層面來看像是穿透了緩存層直接達到db,從而稱為緩存穿透,沒有了緩存層的保護,這種查詢一定不存在的數據對系統來說可能是一種危險,如果有人惡意用這種一定不存在的數據來頻繁請求系統(准確的說是攻擊系統),請求都會到達數據庫層導致db癱瘓從而引起系統故障。

解決方案
在緩存使用的場景中,緩存KEY值失效的風暴(單個KEY值失效,PUT時間較長,導致穿透緩存落到DB上,對DB造成壓力)。可以采用 布隆過濾器 、單獨設置個緩存區域存儲空值,對要查詢的key進行預先校驗 、緩存降級等方法。
緩存穿透業內的解決方案已經比較成熟,主要常用的有以下幾種:

  • bloom filter:類似於哈希表的一種算法,用所有可能的查詢條件生成一個bitmap,在進行數據庫查詢之前會使用這個bitmap進行過濾,如果不在其中則直接過濾,從而減輕數據庫層面的壓力。guava中有實現BloomFilter算法
  • 空值緩存:一種比較簡單的解決辦法,在第一次查詢完不存在的數據后,將該key與對應的空值也放入緩存中,只不過設定為較短的失效時間,例如幾分鍾,這樣則可以應對短時間的大量的該key攻擊,設置為較短的失效時間是因為該值可能業務無關,存在意義不大,且該次的查詢也未必是攻擊者發起,無過久存儲的必要,故可以早點失效。

2.緩存雪崩
  在普通的緩存系統中一般例如redis、memcache等中,我們會給緩存設置一個失效時間,但是如果所有的緩存的失效時間相同,那么在同一時間失效時,所有系統的請求都會發送到數據庫層,db可能無法承受如此大的壓力導致系統崩潰。

解決方案
加鎖排隊、 設置過期標志更新緩存 、 設置過期標志更新緩存 、二級緩存(引入一致性問題)、 預熱、 緩存與服務降級

  • 線程互斥:只讓一個線程構建緩存,其他線程等待構建緩存的線程執行完,重新從緩存獲取數據才可以,每個時刻只有一個線程在執行請求,減輕了db的壓力,但缺點也很明顯,降低了系統的qps。
  • 交錯失效時間:這種方法時間比較簡單粗暴,既然在同一時間失效會造成請求過多雪崩,那我們錯開不同的失效時間即可從一定長度上避免這種問題,在緩存進行失效時間設置的時候,從某個適當的值域中隨機一個時間作為失效時間即可。

3.緩存擊穿
  緩存擊穿實際上是緩存雪崩的一個特例,緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期),這時由於並發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引起數據庫壓力瞬間增大,造成過大壓力。擊穿與雪崩的區別即在於擊穿是對於某一特定的熱點數據來說,而雪崩是全部數據
解決方案

-雙重校驗(Dubbo Check)類似線程安全的懶漢單例模式實現,保證只會有一個線程去訪問數據庫

總結

針對業務系統,永遠都是具體情況具體分析,沒有最好,只有最合適。
最后,對於緩存系統常見的緩存滿了和數據丟失問題,需要根據具體業務分析,通常我們采用LRU策略處理溢出,Redis的RDB和AOF持久化策略來保證一定情況下的數據安全。

參考:
https://blog.csdn.net/sanyaoxu_2/article/details/79472465


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM