redis的作用
一般情況下Redis是用來實現應用和數據庫之間的一個讀操作的緩存層,主要目的是減少數據庫的io,還可以提升數據庫io性能
方法一:
先更新MySQL數據庫,再刪除緩存,再從數據庫查詢到的最新的數據同步到redis。采用最終一致性性策略。
缺點:相較于mq的方式,這種方式由于要查數據庫并將最新數據寫到redis,可能會造成接口響應速度變慢。
方法二:
更新mysql數據庫,再采用mq異步的方式,將數據同步到redis中。
缺點:數據同步延時概率比較大,數據庫的更改信息投遞到mq中,消費者可能沒來得及消費消息同步數據到redis。
優點:異步解耦
方法三:
基于訂閱mysql binlog,采用mq異步的形式將數據同步到redis(canal框架)。
將mysql以主從的方式部署,主庫負責寫,從庫負責讀,當主庫的binlog日志文件發生改變時,將信息同步到從庫,從庫執行對應的sql,保證主從一致性。
canalServer端,偽裝成mysql的從節點,訂閱mysql主節點的binlog文件,當主節點的binlog發生變化時,會將binlog日志文件發送給canalServer端,自己創建的處理程序連接到canalServer端,將數據同步到redis。
優點:手動直接更改數據庫也會自動同步到redis。
方法四:
延時雙刪策略(不推薦)
- 先刪緩存,在更新mysql并同步到redis,在高并發的情況下,第一個線程還沒來得及更新mysql時,其他線程讀取到的緩存可能為null值,將mysql舊的數據同步到redis中了。
解決辦法:延時刪除,在t1線程更新數據庫之后,sleep一段時間再去刪除緩存。
缺點:t1線程延時多少秒再去刪除緩存中的key?難以控制,得根據業務邏輯的執行時間和寫緩存的時間來進行估算。
補充:什么是雙寫一致性協議?
先更新數據庫,在更新緩存。
updateDB();
updateredis();
多個線程同步修改mysql和redis時,由于mysql行鎖機制,多個線程同時修改同一行數據,只能有一個線程修改成功,兩個線程更新完數據庫后同時更新redis,由于不能確保兩個線程更新緩存的先后順序,可能會造成數據庫和緩存的不一致性。
解決辦法:使用事務保證更新數據庫和更新緩存整個兩個操作的原子性。