前言
在讀寫分離的情況下,緩存和數據庫數據不一致怎么解決? 請看這一篇如何更新緩存保證緩存和數據庫雙寫一致性?
如何解決DB數據庫的數據不一致問題? 請看這一篇怎么解決DB讀寫分離,導致數據不一致問題?
在緩存和數據庫數據一致性問題中,推薦 先更新數據庫,再刪除緩存。如果緩存刪除失敗可以用MQ消息隊列的方式進行重試刪除。
為什么會導致不一致
上圖流程:
1)應用服務(商品服務)請求A更新庫存為99,原值為100
2)但主庫同步到從庫需要時間,還沒有同步完成時,請求B發起讀請求
3)讀請求B走的是從庫,取出來從庫里面的舊值100
4)讀請求B會把取出來的值,再設置到緩存中,值為100
5)但當從庫同步數據完成,從庫的數據值為99,這就導致數據庫和緩存數據不一致
方案一:后台緩存標記法
怎么解決DB讀寫分離,導致數據不一致問題?里面提到此方案,這邊就不重復介紹了,大家可以去那篇文章中查看。
數據不一致問題是因為讀請求走的是從庫,把從庫的舊值又設置到緩存中了。后台緩存標記方案就解決了此問題,在主從數據庫同步窗口時間內,讀請求也是走主庫。這樣就解決了讀請求取到的是舊值這個問題。
但這個方案也有缺點,就是有系統性能問題,降低了吞吐量
方案二:延遲消息
其實在真實業務中,尤其互聯網項目中,數據短時間的不一致時能夠接受的。就像怎么解決DB讀寫分離,導致數據不一致問題?中提到的本地緩存標記法,保證了本用戶數據一致,其他用戶可暫時不一致,但最終是一致的這個思路。我們可以設置一個延遲消息,如下圖
流程:
1)在訂閱到binlog更新日志時,先不刪除緩存,而是投遞一個延遲消息(如:延遲10秒的消息,就是過10秒此消息才會被消費者監聽到,從而被消費)
2)延遲消息的延遲時間,設置為主庫與從庫的數據同步延遲的時間,可自行預估
3)監聽到延遲消息,在刪除緩存。
這個方案的特點就是讀請求會在延遲時間內讀取到的是舊值,等到延遲時間一過,取到的就是新值。這個業務在互聯網產品中是允許的。
如果要保證本用戶(更新數據的用戶)一定讀到的是新值,這邊可以采用本地緩存標記方案,直接從主數據庫讀取,讀取到數據后,可以把新值設置到緩存中,這樣就保證了數據一致性。
方案三:更新用戶再次發起讀請求
在方案二中,其他用戶的讀請求會有暫時間讀取到的是舊值,如何縮短時間?其實是有一個方案,就是讓更新用戶再次發起讀請求,也就是在方案二最后提到的
1)更新用戶再次發起讀請求,根據本地緩存標記,直接走主數據庫,讀取的肯定是新值,
2)再把這個新值設置到緩存中。這樣就保證了緩存中的是新值,雖然從庫還沒有不同完成,但緩存中已經是新值了。
3)最后從庫同步數據完成,值就達到了一致性
此方案的問題:就是更新操作后,多了一步讀請求。
總結:小伙伴可以根據自己的業務需求,選擇不同的方案,一定要結合自己的業務,沒有什么完美的方案,只是如何取舍而已。