Redis和數據庫同步更新的正確方法

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

視圖分析:

1.寫流程(更新策略)

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

2.讀流程

先讀 cache,如果數據命中 hit 則返回;
如果數據未命中 miss 則讀 DB;
將 DB 中讀取出來的數據入緩存。

什麼情況下可能出現緩存和數據庫不一致呢?
在這裏插入圖片描述

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

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

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

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