首頁  >  文章  >  資料庫  >  MySQL資料怎麼同步到Redis緩存

MySQL資料怎麼同步到Redis緩存

王林
王林轉載
2023-05-27 09:08:101348瀏覽

1 Mysql查完數據,再同步寫入到Redis中

缺點1:會對介面造成延遲,因為同步寫入redis本身就有延遲,也要做重試,如果redis寫入失敗,還需要重試,那就更花時間了。

缺點2:不解耦,如果redis崩了,那直接卡線程了

缺點3:如果人為該資料庫,那就沒法同步了, 除非再人為刪除對應的Redis,但刪除Redis這個過程也有個時間差

2 Mysql查完數據,透過發送MQ,在消費者線程去同步Redis

缺點1:多了層MQ,也就是會有很大的機率導致同步延遲問題.

缺點2:要對MQ的可用性做預防

#缺點3:如果人為該資料庫,那就沒辦法同步了

優點1:可以大幅減少介面的延遲回傳的問題

優點2:MQ本身有重試機制,無需人工去寫重試程式碼

優點3:解耦,把查詢Mysql和同步Redis完全分離,互不干擾

##3 訂閱Mysql的Binlog檔(可藉助Canal來進行)

CanalServer會偽裝成MysqlServer從庫,去訂閱MysqlServer主庫的Binlog檔案

Canal啟動的時候會設定對應的訊息MQ(RabbitMQ, RocketMQ, Kafka), 監聽到Binlog檔案有變化是,會把變化的sql語句轉換成json格式,並當作訊息內容傳送到MQ中

專案中只要監聽對應MQ,就能拿到Binlog改動的內容,Json資料中有明確的操作類型(CURD), 以及對應的資料。把對應資料同步到redis即可

缺點1:canal訂閱Binlog的整個操作過程是單執行緒的,所以面臨超高並發的情況下,效能可能不太出色。你可以部署多個Canal與多個消費者,但需要注意避免重複消費問題,並進行冪等性校驗

優點1:即使人為改數據庫,也會監聽到,並且也會同步

優點2:非同步同步,不會對介面回傳有格外延遲

4 延遲雙刪

在執行修改sql之前,先將redis的資料刪除

執行更新sql

延遲一段時間

再次刪除redis的資料

// 延迟双删伪代码
deleteRedisCache(key);   // 删除redis缓存
updateMysqlSql(obj);        // 更新mysql
Thread.sleep(100);           // 延迟一段时间
deleteRedisCache(key);   // 再次删除该key的缓存

缺點:這個延遲時間不好把控,到底延遲多久,這個很難去評估

如果不採用延遲雙刪的方式,只是將快取刪除,然後修改MySQL資料。只有這兩步會出現什麼問題呢?

5. 單一請求,單線程沒問題,高並發多線程下會出問題

6. 如果Thread1線程要更新數據,此時Thread1線程把redis清理了

7. 此時Thread2執行緒來了,但Thread1還沒更新mysql完畢

#8. Thread2查詢redis肯定是null,此時Thread2就要查mysql了,然後再把查到的數據寫到快取

9. 由於Thread1還沒來得及修改mysql數據,所以此時Thread2查出來的數據是【舊數據】,Thread2把舊數據又寫入Redis 了

10 . 此時Thread3線程來了,查詢Redis發現有數據,則直接拿緩存數據了,此時【Thread3查出來的是舊數據】,直接帶著舊數據返回了,這就是問題所在

11. 而延遲雙刪的第二次刪除作用就是防止Thread2把舊資料又寫入了,有了延遲雙刪,Thread3查詢Redis的時候還是null,就會從mysql 去拿最新資料了

12. 所以正常的這個延遲時間,應該是Thread2查緩存到拿mysql數據,到再保存到redis這整個時間,作為Thread1的延遲時間,但是這個Thread2這個過程的時間會受到很多因素影響,因此很難斷定究竟會是多久

5 延遲雙寫

// 延迟双写伪代码
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存

上述程式碼缺陷;

  • 高並發下,兩個執行緒同時執行上面程式碼,並對mysql 修改,且修改內容不通,可能會導致Redis與Mysql資料不一致

  • T1執行緒執行完updateMysqlSql,釋放了行鎖,此時T2執行緒再執行updateMysqlSql 與addRedis, 最後T1執行addRedis,這種情況會導致資料庫改成了T2線程的數據,但Redis卻是T1線程的數據

優化

// 完美延迟双写伪代码
开启事务
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存
提交事务

上述程式碼改正:

把兩句程式碼放到一個交易裡面,只有T1執行完Mysql 與Redis的時候,T2才能開始執行,就可以確保資料一致性。建議使用分散式鎖定

雙寫缺點:Mysql 與 Redis是單線程的。性能方面不行,因此不建議使用

以上是MySQL資料怎麼同步到Redis緩存的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除