Redis緩存篇(四)緩存異常

這一節,咱們來學習一下緩存異常。緩存異常有四種類型,分別是緩存和數據庫的數據不一致、緩存雪崩、緩存擊穿和緩存穿透。html

下面經過了解這四種緩存異常的原理和應對方法。前端

緩存和數據庫的數據不一致

緩存和數據庫的數據一致性包含兩種狀況:數據庫

  • 緩存中有數據,緩存的數據值須要和數據庫中的值相同;
  • 緩存中沒有數據,數據庫中的值必須是最新值。

數據不一致是如何發生的?

第1講中關於緩存的類型那節,介紹了緩存有兩種不一樣類型,分別是隻讀緩存和讀寫緩存。不一樣類型的緩存數據不一致的發生狀況不同,應對方法也不同。後端

讀寫緩存:有兩種寫回策略,同步直寫和異步寫回。若是要保證數據一致,就要採用同步直寫策略。但須要保證緩存和數據庫的更新具備原子性,即要麼都成功,要麼都失敗。數組

只讀緩存:分新增數據和刪改數據兩種狀況說明。緩存

新增數據異步

數據直接寫到數據庫中,不對緩存作任何操做,符合一致性的第2種狀況。函數

刪改數據學習

發生刪改操做時,既要更新數據庫,也要在緩存裏刪除數據。由於緩存和數據庫是不一樣的系統,這裏分兩種狀況:指針

  • 先刪除緩存,再更新數據庫:數據庫更新失敗,致使請求再次訪問緩存時,發現緩存失敗,再讀數據庫時,從數據庫中讀取舊值。
  • 先更新數據庫,再刪除緩存:緩存刪除失敗,致使請求再次訪問緩存時,發現緩存命中,並從緩存中讀取到舊值。

如何解決數據不一致?

使用重試機制,指把刪除的緩存值或者是要更新的數據庫值暫存到消息隊列中(例如使用Kafka消息隊列)。

當應用沒有可以成功地刪除緩存值或者是更新數據庫值時,從消息隊列中從新讀取這些值,而後再次進行刪除或更新。

若是成功刪除,就從消息隊列中刪除,以避免重複操做。不然就要進行重試,若是重試超過必定次數,就要向業務層發送報錯信息。

具體狀況以下圖所示:

image

總結一下,對於只讀緩存來講,建議優先使用先更新數據庫,再刪除緩存

緩存雪崩

緩存雪崩,指大量的應用請求沒法在Redis緩存中進行處理,而後應用將大量請求發送到數據庫層,致使數據庫層的壓力激增。

致使緩存雪崩的兩個緣由:

1. 緩存中有大量數據同時過時,致使大量請求沒法獲得處理。

解決方案有兩個,一是避免給大量的數據設置相同的過時時間,增長一個較小的隨機數(例如,隨機增長1~3分鐘)。

另外一個是服務降級,服務降級指發生緩存雪崩時,針對不一樣的數據採起不一樣的處理方式:

  • 非核心數據,暫時中止從緩存中查詢,直接返回預約義信息、空值或者錯誤信息;
  • 核心數據,容許查詢緩存,若是緩存缺失,繼續經過數據庫讀取。

2. Redis緩存實例發生故障宕機了,沒法處理請求。

有兩個建議,一是在業務系統中實現服務熔斷或請求限流機制

服務熔斷是指在發生緩存雪崩時,爲了防止引起連鎖的數據庫雪崩,暫停業務應用對緩存系統的接口訪問。

具體點,就是業務應用調用緩存接口時,緩存客戶端並不把請求發給Redis緩存實例,而是直接返回,等Redis緩存實例從新恢復服務後,再容許發送。

服務熔斷會暫停了整個緩存系統的訪問,對業務應用的影響範圍大。而請求限流相比服務熔斷形成的影響沒那麼大。

請求限流是指業務系統的請求入口前端控制每秒進入系統的請求數,避免過多的請求被髮送到數據庫。

二是事前預防,經過主從節點構建Redis緩存高可靠集羣。

緩存擊穿

緩存擊穿,指針對某個訪問很是頻繁的熱點數據的請求,沒法在緩存中進行處理,大量請求發送到後端數據庫,致使數據庫壓力激增,影響數據庫處理其餘請求。

解決方案是,對於訪問特別頻繁的熱點數據,不設置過時時間

緩存穿透

緩存穿透,指要訪問的數據既不在Redis緩存中,也不在數據庫中,致使請求在訪問緩存時,發生緩存缺失,再去訪問數據庫時,也發現沒有數據。

若是有大量請求訪問數據,就會同時給緩存和數據庫帶來巨大壓力。

發生緩存穿透有兩種狀況:

  • 業務層誤操做:緩存中的數據和數據庫中的數據被誤刪除;
  • 惡意攻擊:專門訪問數據庫中沒有的數據。

爲了不緩存穿透,有三種應對方案。

第一種方案是,緩存空值或缺省值

一旦發生緩存穿透,就針對查詢的數據,在Redis中緩存一個空值或是和業務層協商肯定的缺省值。

第二種方案是,使用布隆過濾器快速判斷數據是否存在,避免從數據庫中查詢數據是否存在,減輕數據庫壓力

布隆過濾器由一個初值都爲0的bit數組和N個哈希函數組成,能夠用來快速判斷某個數據是否存在。

經過三個操做完成標記:

  • 使用N個哈希函數,分別計算這個數據的哈希值,獲得N個哈希值
  • 把這N個哈希值對bit數組的長度取模,獲得每一個哈希值的位置
  • 把對應的位置的bit位設置爲1

這樣一來,即便發生緩存穿透,大量請求只會查詢Redis和布隆過濾器。

第三種方案是,在請求入口的前端進行請求檢測

例如對請求進行合法性檢測,把惡意的請求(例如請求參數不合理、請求參數是非法值、請求字段不存在)直接過濾掉

總結

image

另外還有三個建議:

  • 針對緩存雪崩,合理地設置數據過時時間,以及搭建高可靠緩存集羣。
  • 針對緩存擊穿,在緩存訪問很是頻繁的熱點數據時,不要設置過時時間。
  • 針對緩存穿透,提早在入口前端實現惡意請求檢測,或者規範數據庫的數據刪除操做,避免誤刪除。

參考資料

相關文章
相關標籤/搜索