如何保證Redis與數據庫的數據一致性


一般來說,只要你用到了緩存,不管是Redis還是memcache,就可能會涉及到數據庫緩存與數據的一致性問題,這里我們以Redis為例。

我們該如何保證Redis與數據庫的一致性呢?

 So easy:

  • 更新的時候,先更新數據庫,然后再刪除緩存。
  • 讀的時候,先讀緩存;如果沒有的話,就讀數據庫,同時將數據放入緩存,並返回響應。

乍一看,一致性問題貌似很好的得到了解決。但仔細一想,你會發現還是有問題:如果先更新了數據庫,刪除緩存的時候失敗了怎么辦?那么數據庫中是新數據,緩存中是老數據,數據出現不一致了。

改進方案:

先刪除緩存,后更新數據庫。因為即使后面更新數據庫失敗了,緩存是空的,讀的時候會從數據庫中重新拉,雖然都是舊數據,但數據是一致的。

所以方案就變成了:

  • 更新的時候,先刪除緩存,然后再更新數據庫。
  • 讀的時候,先讀緩存;如果沒有的話,就讀數據庫,同時將數據放入緩存,並返回響應。

 

到這里是不是問題就得到了徹底的解決了呢?其實並沒有,在高並發的場景下,會出現這樣的情況:數據發生了變更,先刪除了緩存,然后去修改數據庫。此時還沒來得及修改,一個請求過來了,去讀緩存,發現緩存空了,去讀數據庫,讀到了准備修改前的舊數據,並且把舊數據放到了緩存。隨后,數據變更程序完成了數據庫的修改。那么完了,這個時候發生數據不一致了......

 

解決方案:

針對這種情況,可以先把“修改DB”的操作放到一個JVM隊列,后面讀請求過來之后,“更新緩存”的操作也放進同一個JVM隊列,每個隊列,對於一個作業線程,按照隊列的順序,依次執行相關操作,這樣就可以保證“更新緩存”一定是在DB修改之后,以保證數據一致性,具體如下圖所示:

細想該方案,其實還有幾個優化點

1、讀請求過多的時候,隊列里面會有多個“更新緩存”操作串在一起,其實是沒有意義的,往隊列里面塞數據的時候可以先判斷一下,有的話就不用再塞進去了

2、遇到更新DB比較頻繁的業務場景時,可能會導致讀請求長時間阻塞,這個時候可以通過擴機器增加吞吐量,或者可以先返回一個舊的值。


免責聲明!

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



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