如何保持MySQL和Redis的一致性?


如題,現在很多架構都采用了Redis+MySQL來進行存儲,但是由於多方面的原因,總會導致Redis和MySQL之間出現數據的不一致性。

      例如如果一個事務執行失敗回滾了,但是如果采取了先寫Redis的方式,就會造成Redis和MySQL數據庫的不一致,再比如說,一個事務寫入了MySQL,但是此時還未寫入Redis,如果這時候有用戶訪問Redis,則此時就會出現數據不一致。

      為了解決這些問題,本文將着重討論,如何保證MySQL和Redis之間存在一個合理的數據一致性方案。

      1、分別處理

      針對某些對數據一致性要求不是特別高的情況下,可以將這些數據放入Redis,請求來了直接查詢Redis,例如近期回復、歷史排名這種實時性不強的業務。而針對那些強實時性的業務,例如虛擬貨幣、物品購買件數等等,則直接穿透Redis至MySQL上,等到MySQL上寫入成功,再同步更新到Redis上去。這樣既可以起到Redis的分流大量查詢請求的作用,又保證了關鍵數據的一致性。

      2、高並發情況下

       此時如果寫入請求較多,則直接寫入Redis中去,然后間隔一段時間,批量將所有的寫入請求,刷新到MySQL中去;如果此時寫入請求不多,則可以在每次寫入Redis,都立刻將該命令同步至MySQL中去。這兩種方法有利有弊,需要根據不同的場景來權衡。

      3、基於訂閱binlog的同步機制

       阿里巴巴的一款開源框架canal,提供了一種發布/ 訂閱模式的同步機制,通過該框架我們可以對MySQL的binlog進行訂閱,這樣一旦MySQL中產生了新的寫入、更新、刪除等操作,就可以把binlog相關的消息推送至Redis,Redis再根據binlog中的記錄,對Redis進行更新。值得注意的是,binlog需要手動打開,並且不會記錄關於MySQL查詢的命令和操作。

       其實這種機制,很類似MySQL的主從備份機制,因為MySQL的主備也是通過binlog來實現的數據一致性。而canal正是模仿了slave數據庫的備份請求,使得Redis的數據更新達到了相同的效果。如下圖就可以看到Slave數據庫中啟動了2個線程,一個是MySQL SQL線程,這個線程跟Matser數據庫中起的線程是一樣的,負責MySQL的業務率執行,而另外一個線程就是MySQL的I/O線程,這個線程的主要作用就是同步Master 數據庫中的binlog,達到數據備份的效果。而binlog就可以理解為一堆SQL語言組成的日志。

轉載自CSDN博客:https://blog.csdn.net/qq_30683329/article/details/80543178


免責聲明!

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



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