1. 程式人生 > >緩存穿透、緩存擊穿、緩存雪崩及其解決方案

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

信息 不存在 相同 但是 崩潰 存儲 搜索 普通 攻擊

1.緩存穿透
  緩存穿透是指查詢一個一定不存在的數據,因為緩存中也無該數據的信息,則會直接去數據庫層進行查詢,從系統層面來看像是穿透了緩存層直接達到DB,從而稱為緩存穿透,沒有了緩存層的保護,這種查詢一定不存在的數據對系統來說可能是一種危險,如果有人惡意用這種一定不存在的數據來頻繁請求系統(準確的說是攻擊系統),請求都會到達數據庫層導致DB癱瘓從而引起系統故障。

解決方案

緩存穿透業內的解決方案已經比較成熟,主要常用的有以下幾種:

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

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

解決方案

  • 線程互斥:只讓一個線程構建緩存,其他線程等待構建緩存的線程執行完,重新從緩存獲取數據才可以,每個時刻只有一個線程在執行請求,減輕了db的壓力,但缺點也很明顯,降低了系統的qps。
  • 交錯失效時間:這種方法時間比較簡單粗暴,既然在同一時間失效會造成請求過多雪崩,那我們錯開不同的失效時間即可從一定長度上避免這種問題,在緩存進行失效時間設置的時候,從某個適當的值域中隨機一個時間作為失效時間即可。
  1. 緩存擊穿
    緩存擊穿實際上是緩存雪崩的一個特例,大家使用過新浪的應該都知道,新浪微博有一個熱門話題的功能,用戶對於熱門話題的搜索量往往在一些時刻會大大的高於其他話題,這種我們成為系統的“熱點“,由於系統中對這些熱點的數據緩存也存在失效時間,在熱點的緩存到達失效時間時,此時可能依然會有大量的請求到達系統,沒有了緩存層的保護,這些請求同樣的會到達db從而可能引起故障。擊穿與雪崩的區別即在於擊穿是對於特定的熱點數據來說,而雪崩是全部數據

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