緩存穿透、緩存雪崩、緩存擊穿的概念及解決辦法

一.緩存穿透:java

     緩存穿透是指查詢一個必定不存在的數據,因爲緩存是不命中時須要從數據庫查詢,查不到數據則不寫入緩存,這將致使這個不存在的數據每次請求都要到數據庫去查詢,形成緩存穿透。數據庫

     解決辦法:數組

     1.布隆過濾緩存

  對全部可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則丟棄。還有最多見的則是採用布隆過濾器,將全部可能存在的數據哈希到一個足夠大的bitmap中,一個必定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。併發

  補充:異步

      Bloom filter函數

  適用範圍:能夠用來實現數據字典,進行數據的判重,或者集合求交集性能

  基本原理及要點:對於原理來講很簡單,位數組+k個獨立hash函數。將hash函數對應的值的位數組置1,查找時若是發現全部hash函數對應位都是1說明存在,很明顯這個過程並不保證查找的結果是100%正確的。同時也不支持刪除一個已經插入的關鍵字,由於該關鍵字對應的位會牽動到其餘的關鍵字。因此一個簡單的改進就是counting Bloom filter,用一個counter數組代替位數組,就能夠支持刪除了。添加時增長計數器,刪除時減小計數器。spa

     2. 緩存空對象. 將 null 變成一個值.線程

  也能夠採用一個更爲簡單粗暴的方法,若是一個查詢返回的數據爲空(不論是數 據不存在,仍是系統故障),咱們仍然把這個空結果進行緩存,但它的過時時間會很短,最長不超過五分鐘。

 緩存空對象會有兩個問題:

 第一,空值作了緩存,意味着緩存層中存了更多的鍵,須要更多的內存空間 ( 若是是攻擊,問題更嚴重 ),比較有效的方法是針對這類數據設置一個較短的過時時間,讓其自動剔除。

 第二,緩存層和存儲層的數據會有一段時間窗口的不一致,可能會對業務有必定影響。例如過時時間設置爲 5分鐘,若是此時存儲層添加了這個數據,那此段時間就會出現緩存層和存儲層數據的不一致,此時能夠利用消息系統或者其餘方式清除掉緩存層中的空對象。

 

 

二.緩存雪崩

    若是緩存集中在一段時間內失效,發生大量的緩存穿透,全部的查詢都落在數據庫上,形成了緩存雪崩。

    這個沒有完美解決辦法,但能夠分析用戶行爲,儘可能讓失效時間點均勻分佈。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的併發請求落到底層存儲系統上。

 

    解決方法

   1. java鎖實現限流

 在緩存失效後,經過互斥鎖來控制讀數據庫寫緩存的線程數量。好比對某個key只容許一個線程查詢數據和寫緩存,其餘線程等待。

 

    2.數據預熱

  能夠經過緩存reload機制,預先去更新緩存,再即將發生大併發訪問前手動觸發加載緩存不一樣的key,設置不一樣的過時時間,讓緩存失效的時間點儘可能均勻

 

     3.給緩存的失效時間,加上一個隨機值,避免集體失效

 

     4.作二級緩存,或者雙緩存策略。

     A1爲原始緩存,A2爲拷貝緩存,A1失效時,能夠訪問A2,A1緩存失效時間設置爲短時間,A2設置爲長期。

    咱們有兩個緩存,緩存A和緩存B。緩存A的失效時間爲20分鐘,緩存B不設失效時間。本身作緩存預熱操做。而後細分如下幾個小點:

  I 從緩存A讀數據庫,有則直接返回
  II A沒有數據,直接從B讀數據,直接返回,而且異步啓動一個更新線程。

  III 更新線程同時更新緩存A和緩存B。

 

      5.緩存永遠不過時

 這裏的「永遠不過時」包含兩層意思:

    (1) 從緩存上看,確實沒有設置過時時間,這就保證了,不會出現熱點key過時問題,也就是「物理」不過時。

     (2) 從功能上看,若是不過時,那不就成靜態的了嗎?因此咱們把過時時間存在key對應的value裏,若是發現要過時了,經過一個後臺的異步線程進行緩存的構建,也就是「邏輯」過時.

 從實戰看,這種方法對於性能很是友好,惟一不足的就是構建緩存時候,其他線程(非構建緩存的線程)可能訪問的是老數據,可是對於通常的互聯網功能來講這個仍是能夠忍受。

 

緩存擊穿

指的是熱點key在某個特殊的場景時間內剛好失效了,剛好有大量併發請求過來了,形成DB壓力。

解決辦法

與緩存雪崩的解決方法相似: 用加鎖或者隊列的方式保證緩存的單線程(進程)寫,在加鎖方法內先從緩存中再獲取一次,沒有再查DB寫入緩存。 

還有一種比較好用的(針對緩存雪崩與緩存擊穿):

物理上的緩存是不設置超時時間的(或者超時時間比較長), 可是在緩存的對象上增長一個屬性來標識超時時間(此時間相對小)。 當獲取到數據後,校驗數據內部的標記時間,斷定是否快超時了,若是是,異步發起一個線程(控制好併發)去主動更新該緩存。

這種方式會致使必定時間內,有些請求獲取緩存會拿到過時的值,看業務是否能接受而定。

相關文章
相關標籤/搜索