在開發中會面臨緩存異常可能會出現三個問題,分别是緩存雪崩、緩存擊穿和緩存穿透。這三個問題會導緻大量請求從緩存轉移到資料庫,如果請求的并發量很大的話,就會導緻資料庫崩潰。是以在面試官也會經常問這些問題。
緩存雪崩是指大量的請求無法在緩存中處理,進而将請求轉移到資料庫中,導緻資料壓力倍增。一個Redis執行個體可以支援萬級别的并發請求,而單個資料庫隻能支援千級别的并發請求。兩者處理請求并發能力相差十倍,資料庫會由于壓力過大而導緻雪崩。
這裡雪崩一般是由兩個原因組成,很多文章隻寫緩存同時過期的情況。

一般設定緩存資料會設定緩存時間,在某一時刻,大量的緩存同時過期,此時如果有請求通路這些資料的話,緩存不存在,會将請求轉移到資料庫,如果這些的請求量比較大的,導緻資料庫的壓力增大,嚴重會導緻資料庫崩潰。
針對大量緩存同時失效帶來的雪崩,有兩種解決方案。
應該避免給資料設定相同的過期時間,在設定過期時間時,增加一點随機值。
服務降低,比如使用hystrix,是指發生雪崩時,針對不同的資料采取不同的處理方式。
請求資料是非核心資料(比如商品屬性),暫時停止從緩存查詢資料,直接傳回預定資訊、空值或者錯誤值。
請求資料是核心資料(比如商品庫存、價格),仍然查詢緩存,如果緩存缺失,繼續在資料庫讀取。
redis服務發生當機,無法處理請求,這就會導緻全部轉移到資料庫去,發生雪崩。
服務熔斷,就是發生雪崩時,暫停對緩存的通路。等redis服務恢複正常後,再允許通路緩存。
對redis所在的伺服器進行名額監控,比如QPS、CPU使用率、記憶體使用率等,如果發現redis服務當機,而資料庫請求壓力倍增,此時可以啟動熔斷機制,暫停對緩存和資料庫的通路,比如使用Hystrix服務熔斷。
但是暫停對緩存系統的通路,但是對整個業務系統影響很大,導緻很多資料不能檢視。為了減少這種影響還有另一個方案:請求限流。
請求限流,就是限制前端請求每秒請求量,使得資料庫能承受前端全部請求。
比如前端允許每秒通路1000次,其中900請求緩存,100次才請求資料庫。
一旦發生雪崩,資料庫每秒請求激增到1000次,此時啟動請求限流,在前端入口隻允許每秒請求100次,過多的請求直接拒絕。
無論使用服務熔斷或請求限流都是是發生雪崩後處理,這裡還有事先預防的方案。
通過主從節點的方式建構redis叢集,如果redis主節點當機,從節點可以切換成主節點。
緩存擊穿是指,針對某個通路緩存非常頻繁,無法在緩存中處理,通路該資料的請求一下子都請求資料庫,導緻資料庫壓力倍增。
對于通路特别頻繁的熱點資料,就不設定過期時間
如果緩存失效,隻有拿到鎖才能通路資料庫,降低資料庫并發通路。
緩存雪崩和緩存擊穿的差别在于雪崩是大量的緩存,擊穿是單一的緩存。
緩存穿透是指通路的資料既不在redis緩存中,也不在資料庫中,因為資料庫也不存在資料,也無法将資料庫資料寫入緩存中,每次請求都要請求緩存和伺服器。不過這樣也導緻系統性能下降。
緩存穿透會發生如下兩種情況:
誤操作,删除了緩存和資料的資料。
惡意攻擊: 專門通路資料庫中不存在的資料。
發生緩存穿透,在redis中緩存一個空值或者實作預選設定好的值(比如0),後續請求查詢直接在redis中讀取空值或者預設值。
布隆過濾器由一個初值都為0的bit數組和N個哈希函數組成,可以用來快速判斷某個資料是否存在。當資料寫入資料庫時,布隆過濾器會通過三個操作完成标記:
使用N個hash函數,分别計算這個資料的hash值,得到N個hash值。
把這N個hash值對bit數組的長度取模,得到每個hash值在數組中對位置。
把對應位置設定為1。如果資料不存在,那麼就沒用使用布隆過濾器标記過資料,那麼,bit數組對應的bit位為零。隻要bit數組有一個不為1,就表明布隆過濾器就沒标記過該資料。
把資料寫入資料庫時,使用布隆過濾器做标記
當緩存消失後,在去資料庫查詢之前,通過查詢布隆過濾器判斷資料是否存在,如果不存在,就不查詢資料庫。
還有在請求入庫添加檢測,把惡意請求(參數不合理、參數非法、參數不存在或者id小于0)直接過濾掉。
緩存雪崩
* 電商首頁資料(電腦端、手機端),比如分類。設定這一類的緩存需要給過期時間添加随機數
緩存擊穿
電商首頁的猜你喜歡商品,不設定逾時時間,或者設定互斥鎖
緩存穿透
電商商品詳情中請求不存在的id,首先要設定入口驗證,然後使用布隆過濾器,不存在直接傳回
緩存雪崩和緩存擊穿主要是資料不在緩存上,而緩存穿透是資料既不在緩存上,也不在資料上。
給過期時間加上小的随機數
服務降級
服務熔斷
請求限流
redis 設定主從叢集
不設定過期時間
入口進行合法性驗證
使用空值或者預設值
使用布隆過濾器快速判斷
使用服務降低、請求熔斷、請求限制會影響使用者使用體驗,最好使用預防方案。
針對緩存雪崩,合理設定資料過期時間,以及搭建redis主從叢集。
針對緩存擊穿,不要設定過期時間。
針對緩存穿透,在請求入口做規範校驗,以及使用布隆過濾器判斷資料是否存在。
如何解決緩存雪崩、擊穿、穿透難題