乙個經典的問題,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作為記憶體快取,只是他查詢快的一大優勢,關係型資料庫只能用作儲存重要資料,或者備份快取的資料,這個時候,不可避免,我們會遇到快取中的資料與關係型資料庫中的資料不一致的情況。出現不一致的現象很常見,如果你是單個使用者肯定不會出現這種情況,如果在多執行緒併發的情況下...