Redis更新的正確方法

原文(緩存更新的套路):看到好些人在寫更新緩存數據代碼時,先刪除緩存,而後再更新數據庫,然後續的操做會把數據再裝載的緩存中。然而,這個是邏輯是錯誤的。試想,兩個併發操做,一個是更新操做,另外一個是查詢操做,更新操做刪除緩存後,查詢操做沒有命中緩存,先把老數據讀出來後放到緩存中,而後更新操做更新了數據庫。因而,在緩存中的數據仍是老的數據,致使緩存中的數據是髒的,並且還一直這樣髒下去了。html

視圖分析:shell

寫流程(更新策略)數據庫

  1. 先淘汰 cache(刪除緩存);
  2. 再寫 DB(更新數據庫)。

讀流程緩存

  1. 先讀 cache,若是數據命中 hit 則返回;
  2. 若是數據未命中 miss 則讀 DB;
  3. 將 DB 中讀取出來的數據入緩存。

什麼狀況下可能出現緩存和數據庫不一致呢?併發

在分佈式環境下,數據的讀寫都是併發的,上游有多個應用,經過一個服務的多個部署(爲了保證可用性,必定是部署多份的),對同一個數據進行讀寫,在數據庫層面併發的讀寫並不能保證完成順序,也就是說後發出的讀請求極可能先完成(讀出髒數據):分佈式

  1. 發生了寫請求 A,A 的第一步淘汰了 cache(如上圖中的1);
  2. A 的第二步寫數據庫,發出修改請求(如上圖中的2);
  3. 發生了讀請求 B,B 的第一步讀取 cache,發現 cache 中是空的(如上圖中的步驟3);
  4. B 的第二步讀取數據庫,發出讀取請求,此時 A 的第二步寫數據還沒開始,讀出了一個髒數據放入 cache(如上圖中的步驟4)。

最終致使緩存與數據庫不一致。spa

先更新數據庫,後刪除緩存建議,使用場景最多),可是,是否是這個就不會有併發問題了?不是的,好比,一個是讀操做,可是沒有命中緩存,而後就到數據庫中取數據,此時來了一個寫操做,寫完數據庫後,讓緩存失效,而後,以前的那個讀操做再把老的數據放進去,因此,會形成髒數據。3d

相關文章
相關標籤/搜索