怎樣保證緩存一致性問題?

什麼是緩存

百度百科定義

> **緩存(cache)**,原始意義是指訪問速度比一般[隨機存取存儲器](https://baike.baidu.com/item/隨機存取存儲器)(RAM)快的一種高速存儲器,通常它不像系統主存那樣使用[DRAM](https://baike.baidu.com/item/DRAM)技術,而使用昂貴但較快速的[SRAM](https://baike.baidu.com/item/SRAM)技術。緩存的設置是所有現代計算機系統發揮高性能的重要因素之一。

從整個計算機的發展史可以看出,緩存在提高計算機性能作出巨大貢獻例如:CPU緩存(一級緩存、二級緩存、三級緩存)、磁盤緩存、系統緩存、網絡緩存、分佈式緩存等等。緩存的終結目的也是提高性能、減少數據IO操作和數據溯源等,那麼本篇文章主要的是在論述分佈式緩存數據的一致性問題。

什麼是緩存一致性

​ 這裏的緩存一致性最主要的是在討論在分佈式緩存的架構下緩存的一致性問題,如圖:

cache1

我們在讀取數據庫數據的時候首先讀取分佈式緩存是否存在數據,如果存在就直接返回,如果不存在數據就從數據庫讀取數據同時緩存數據到分佈式緩存中,那麼如果存在另外一個線程在更新數據庫數據,那麼我們應該怎樣去更新緩存數據,才能保證數據庫和緩存的數據的一致性呢?

解決方案

數據實時同步

​ 首先這種數據同步是增量、主動、強一致性,首先思路

  • 對數據庫數據進行更新的時候(新增刪除更新)淘汰緩存(緩存失效)

  • 讀取數據的時候更新緩存,爲了避免緩存擊穿帶來的雪崩問題我們需要做同步處理,控制只有一個線程去讀取數據然後更新到緩存,其他線程被阻塞等待

  • 設置緩存失效時間,這是一個兜底操作假設在更新緩存失敗這個緩存失效時間一到就會把緩存失效

    流程圖

cache2

數據準實時性

​ 首先這種數據同步是增量、被動、準一致性,首先思路

  • 對數據進行更新操作時在保持數據庫後發送一個更新緩存的MQ消息(如果要保證數據不丟失,建議可以建立本地一個消息表在發生MQ失敗後可以重試)
  • 緩存更新服務消費MQ更新數據消息後讀取數據庫數據進行相關業務處理(比如需要讀取數據庫數據進行彙總計算操作等)
  • 緩存更新服務更新業務處理結果數據到分佈式緩存中

cache3

任務調度更新

​ 這種通過分佈式調度任務進行定時更新緩存,使用場景如:報表統計數據、對賬數據定時更新到緩存,實現比較簡單

緩存穿透

**現象:**每次請求直接穿透緩存層,直接回源到數據庫中,給數據庫帶來了巨大訪問壓力,甚至宕機。

**原因:**訪問數據會先訪問緩存,如果數據不存在緩存中才會查詢數據庫,但是如果查詢數據庫也查詢不出來數據,也是說當前訪問數據永遠不會寫入緩存中。這樣就導致了,訪問一定不存在的數據,就相當於緩存層形同虛設,每次請求都會到db層,造成數據庫負擔過大。

解決方案:

  • 方案一:採用bloom filter保存緩存過的key,在訪問請求到來時可以過濾掉不存在的key,防止這些請求到db層;
  • 方案二:如果db查詢不到數據,保存空對象到緩存層,設置較短的失效時間;
  • 方案三:針對業務場景對請求的參數進行有效性校驗,防止非法請求擊垮db。

緩存擊穿

**現象:**當某一key失效時,造成大量請求到db層,擊垮存儲層。

**原因:**爲了保證緩存數據的時效性,通常會設置一個失效時間,如果是熱點key,高併發時會有海量請求直接越過緩存層到數據庫,這樣就會給數據庫造成的負擔增大,設置宕機。

解決方案

  • 方案一:使用互斥鎖,當緩存數據失效時,保證一個請求能夠訪問到數據庫,並更新緩存,其他線程等待並重試;
  • 方案二:緩存數據“永遠不過期”,如果緩存數據不設置失效時間的話,就不會存在熱點key過期造成了大量請求到數據庫。但是,緩存數據就變成“靜態數據”,因此當緩存數據快要過期時,採用異步線程的方式提前進行更新緩存數據。

緩存雪崩

**現象:**多個key失效,造成大量請求到db層,導致db層負擔過重甚至宕機。

**原因:**緩存雪崩是指在我們設置緩存時採用了相同的過期時間,導致緩存在某一時刻同時失效,請求全部轉發到數據庫,最終導致數據庫瞬時壓力過大而崩潰。

解決方案:

  • 方案一:使用互斥鎖的方式,保證只有單個線程進行請求能夠達到db;
  • 方案二:多每個key的失效時間在基礎時間上再加上一個1~5分鐘的隨機值,這樣就能保證大規模key集體失效的概率,並且需要儘量讓多個key的失效時間能夠均勻分佈;

我的博客地址

關注我

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章