redis中如何保證緩存數據的一致性


 

 

1.方式一:先更新數據庫,再更新緩存場景

當有兩個線程A、B,同時對一條數據進行操作,一開始數據庫和redis的數據都為tony,當線程A去修改數據庫,將tong改為allen,然后線程A在修改緩存中的數據,可能因為網絡原因出現延遲,這個時候線程B,將數據修改成了Mike、然后將數據庫中的tony,也改成了Mike,然后線程A恢復正常,將redis中的緩存改成了allen,此時就出現了緩存數據和數據庫數據不一致情況。不推薦

2.方式二:先更新緩存,再更新數據庫場景

當有兩個線程A、B,同時對一條數據進行操作,線程A先將redis中 的數據修改為了allen,然后CPU切換到了線程B,將redis中的數據修改為了mike,然后將數據庫中的信息也修改了mike,然后線程A獲得CPU執行,將數據庫中的信息改為了allen,此時出現緩存和數據庫數據不一致情況。不推薦

3.方式三:先刪除緩存,再更新數據庫的場景

當有兩個線程A、B,同時對一條數據進行操作,當線程A進行修改緩存操作時,先刪除掉緩存中的數據,然后去修改數據庫,因為網絡問題出現延遲,這時線程B需要去數據庫中查詢數據為tony,然后將數據更新到緩存中,線程A網絡恢復,又將數據庫數據修改為了allen,此時出現數據不一致。不推薦

 

4.方式四:先更新數據庫,在刪除緩存場景

一改一查場景:

當有兩個線程A、B,線程A先去將數據庫的值修改為allen,然后需要去刪除redis中的緩存,當線程B去讀取緩存時,線程A已經完成delete操作時,緩存不命中,需要去查詢數據庫,然后在更新緩存,數據一致性;如果線程A沒有完成delete操作,線程B直接命中,返回的數據與數據庫中的數據不一致,可能會短暫出現數據不一致情況,但最終都會一致。推薦

存在的問題:當數據過期或者初始化時,會出現數據不一致情況,也就是線程B從數據庫中,查詢到數據為tony,然后線程A將tony修改為了allen,然后去刪除redis中的數據,然后線程B將讀到的tony,更新到了數據庫中,出現了數據不一致問題。

解決方案:對於不過期的數據我們要在上線的時候做好數據的預熱,保證緩存命中。對於存在過期的數據,因為有過期時間,只會在特定的時間段內數據不一致,下次數據過期后,可以恢復,對於實時性要求不高時,可以接受。

兩次修改場景:

當有兩個線程A、B,線程A去修改數據庫中的值改為allen,然后出現網絡波動,線程B將數庫中的值修改為了Mike,然后兩個線程都會刪除緩存,保證數據一致性。

5.方式五:最佳實現,數據異步同步

Canal:基於數據庫增量日志解析,提供增量數據訂閱和消費https://github.com/alibaba/canal

mysql會將操作記錄在Binary log日志中,通過canal去監聽數據庫日志二進制文件,解析log日志,同步到redis中進行增刪改操作。

canal的工作原理:canal 模擬 MySQL slave 的交互協議,偽裝自己為 MySQL slave ,向 MySQL master 發送dump 協議;MySQL master 收到 dump 請求,開始推送 binary log 給 slave (即 canal );canal 解析 binary log 對象(原始為 byte 流)。


免責聲明!

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



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