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

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

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

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

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

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

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

 

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

一改一查場景:

當有兩個線程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,然後兩個線程都會刪除緩存,保證數據一致性。

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

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 流)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章