Redis更新的正確方法


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

視圖分析:

寫流程(更新策略)

  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)。

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

先更新數據庫,后刪除緩存建議,使用場景最多),但是,是不是這個就不會有並發問題了?不是的,比如,一個是讀操作,但是沒有命中緩存,然后就到數據庫中取數據,此時來了一個寫操作,寫完數據庫后,讓緩存失效,然后,之前的那個讀操作再把老的數據放進去,所以,會造成臟數據。

 


免責聲明!

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



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