Redis和資料庫快取一致性問題之我見

2022-09-02 19:18:09 字數 2460 閱讀 7995

乙個經典的問題,redis經常被用來當作快取,那麼redis快取一致性怎麼解決?翻閱了網上很多資料,答案不一,這裡簡單整理一下我的看法。

目錄2 先運算元據庫,後操作快取

2.2 先更新資料庫,再刪快取

3 個人總結

4 番外:從借鑑作業系統的一些方法

參考問題 髒寫

在併發的情況下,可能出現以下情況的問題

解決方案

延時雙刪

思路是,為了避免更新資料庫的時候,其他執行緒從快取中讀取不到資料,就在更新完資料庫之後,再 sleep 一段時間,然後再次刪除快取。

執行緒1刪除快取,然後去更新資料庫。

執行緒2來讀快取,發現快取已經被刪除,所以直接從資料庫中讀取,這時候由於執行緒1還沒有更新完成,所以讀到的是舊值,然後把舊值寫入快取。

執行緒1,根據估算的時間,sleep,由於 sleep 的時間大於執行緒2讀資料+寫快取的時間,所以快取被再次刪除。

如果還有其他執行緒來讀取快取的話,就會再次從資料庫中讀取到最新值。

一定程度下可以保證一致性了,但很很離譜的一點在於要「估算時間」,因為有這種不確定的因素在,可能還是會出問題。

比如估算的時間太短了,還是先刪除快取,再更新舊資料了。

在比如多個執行緒一起延時雙刪,還是會有問題。

簡單來說有兩種方式:

不管會不會出問題,先說說哪種比較好,答案當然是——看情況

接下來分析以下這兩種方式可能出現的問題

問題1 弱一致性

由於磁碟i/o速度慢,在更新資料庫、更新快取這段操作之前,其他執行緒讀取到的都是原本快取中的舊值。

解決方案

如果不要求強一致性,那沒啥問題

如果要求這麼強的一致性,那在更新db前更新一下快取

問題2 更新失敗

更新資料庫成功,如果更新快取失敗或者還沒有來得及更新,那麼,其他執行緒從快取中讀取到的就是舊值,還是會發生不一致

可以引入訊息佇列,並進行重試,保證成功

問題3 髒寫

可能會出現快取「髒寫」造成的髒資料

解決方案:

問題1 刪除失敗

其實和先更新資料庫,再更新快取的問題2一樣

更新資料庫成功,如果更新刪除失敗或者還沒有來得及刪除,那麼,其他執行緒從快取中讀取到的就是舊值,還是會發生不一致

可以引入訊息佇列,並進行重試,保證成功

問題2 髒寫

寫操作先更新資料庫,更新成功後使快取失效

解決方法

這種問題其實有點無解,因為讀資料庫實際上是不會產生binlog的,所以我們即使引入了訊息佇列,也無法保證最後的那個「寫快取」操作什麼時候到來。

值得一提的是,這種問題其實在以上的任何情況,都有可能出現。

個人認為乙個比較好的解決方案就是加鎖,比如讀資料庫的a的時候,我們使用for update加鎖,將「讀資料庫、寫快取」看作乙個完整的事務,「更新資料庫、刪快取」看作乙個完整的事務,通過加鎖來保證原子性。

其實這樣加鎖以後,「先刪快取、後改資料庫的併發問題也可以迎刃而解了

個人認為乙個比較好的方法是先更新後刪除,配合讀資料庫加鎖,如果有必要的話可以引入訊息佇列

cpu向cache寫入資料時,同時向memory(後端儲存)也寫乙份,使cache和memory的資料保持一致。

其實就是上面提到的這些操作

cpu更新cache時,只是把更新的cache區標記一下(髒位),並不同步更新memory(後端儲存)。只是在cache區要被新進入的資料取代時,才更新memory(後端儲存)

其實是乙個挺好的方法,但問題是redis在淘汰的時候我們並不能感知到,而os的話替換是也是os操作的,是可以感知到的

另外乙個問題就是,要引入額外字段

面試官:redis 快取一致性問題怎麼解決,這樣回答簡直完美

redis 快取常見問題:快取一致性的解決方案

快取和資料庫一致性

對應比較常用的資料,比如鑑權資料一般會放在快取中 比如 redis 這樣能夠跟快的實現讀取,所以一般讀取流程如下 目前網上有很多關於快取和資料庫怎麼保持一致性的文件,主要可以總結為如下幾點 1 先更新資料庫,在更新快取 2 先刪除快取,在更新資料庫 3 先更新資料庫,在刪除快取 下面將對著幾種機制作...

redis快取與資料庫一致性

實時同步 對強制性要求比較高的,應採用實時同步方案,先查詢快取若查詢不到再去db中查詢,然後儲存到快取 更新快取時,先更新資料庫,再將快取的設定過期 建議不要去更新快取內容,直接設定快取過期 1.cacheable 查詢時使用,注意long型別需要轉化為string型別,否則會拋棄異常 2.cach...

Redis快取一致性

用過redis的應該都清楚,redis作為記憶體快取,只是他查詢快的一大優勢,關係型資料庫只能用作儲存重要資料,或者備份快取的資料,這個時候,不可避免,我們會遇到快取中的資料與關係型資料庫中的資料不一致的情況。出現不一致的現象很常見,如果你是單個使用者肯定不會出現這種情況,如果在多執行緒併發的情況下...