Redis 面試常見問題———緩存雪崩、緩存擊穿以及緩存穿透


在開發中會面臨緩存異常可能會出現三個問題,分別是緩存雪崩、緩存擊穿和緩存穿透。這三個問題會導致大量請求從緩存轉移到數據庫,如果請求的並發量很大的話,就會導致數據庫崩潰。所以在面試官也會經常問這些問題。

緩存雪崩

緩存雪崩是指大量的請求無法在緩存中處理,從而將請求轉移到數據庫中,導致數據壓力倍增。一個Redis實例可以支持萬級別的並發請求,而單個數據庫只能支持千級別的並發請求。兩者處理請求並發能力相差十倍,數據庫會由於壓力過大而導致雪崩。
這里雪崩一般是由兩個原因組成,很多文章只寫緩存同時過期的情況。
緩存雪崩

原因一:緩存中大量的數據同時過期

一般設置緩存數據會設置緩存時間,在某一時刻,大量的緩存同時過期,此時如果有請求訪問這些數據的話,緩存不存在,會將請求轉移到數據庫,如果這些的請求量比較大的,導致數據庫的壓力增大,嚴重會導致數據庫崩潰。

針對大量緩存同時失效帶來的雪崩,有兩種解決方案。

方案一: 過期時間設置隨機值

應該避免給數據設置相同的過期時間,在設置過期時間時,增加一點隨機值。

setRedis(key, value, time + Math.random() * 10000);

方案二: 服務降級

服務降低,比如使用hystrix,是指發生雪崩時,針對不同的數據采取不同的處理方式。

  • 請求數據是非核心數據(比如商品屬性),暫時停止從緩存查詢數據,直接返回預定信息、空值或者錯誤值。
  • 請求數據是核心數據(比如商品庫存、價格),仍然查詢緩存,如果緩存缺失,繼續在數據庫讀取。
    服務降級

原因二: redis 服務掛了

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主從集群。
  • 針對緩存擊穿,不要設置過期時間。
  • 針對緩存穿透,在請求入口做規范校驗,以及使用布隆過濾器判斷數據是否存在。

參考


免責聲明!

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



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