保持資料庫和redis的資料一致性大致有兩種方案:
一:先洗掉快取,再更新資料庫
該方案會導致不一致的原因是,同時有一個請求A進行更新操作,另一個請求B進行查詢操作,那么會出現如下情形:
- 1)請求A進行寫操作,洗掉快取
- 2)請求B查詢發現快取不存在
- 3)請求B去資料庫查詢得到舊值
- 4)請求B將舊值寫入快取
- 5)請求A將新值寫入資料庫
上述情況就會導致不一致的情形出現,而且,如果不采用給快取設定過期時間策略,該資料永遠都是臟資料,
解決方案:采用延時雙刪策略
二:先更新資料庫,再洗掉快取
假設這會有兩個請求,一個請求A做查詢操作,一個請求B做更新操作,那么會有如下情形產生
- 1)快取剛好失效
- 2)請求A查詢資料庫,得一個舊值
- 3)請求B將新值寫入資料庫
- 4)請求B洗掉快取
- 5)請求A將查到的舊值寫入快取
ok,如果發生上述情況,確實是會發生臟資料
發生上述情況有一個先天性條件,就是步驟(3)的寫資料庫操作比步驟(2)的讀資料庫操作耗時更短,才有可能使得步驟(4)先于步驟(5),可是,大家想想,資料庫的讀操作的速度遠快于寫操作的(不然做讀寫分離干嘛,做讀寫分離的意義就是因為讀操作比較快,耗資源少),因此步驟(3)耗時比步驟(2)更短,這一情形很難出現,
三:最佳解決方案:
方案一
先做一個說明,從理論上來說,給快取設定過期時間,是保證最終一致性的解決方案,這種方案下,我們可以對存入快取的資料設定過期時間,所有的寫操作以資料庫為準,對快取操作只是盡最大努力即可,也就是說如果資料庫寫成功,快取更新失敗,那么只要到達過期時間,則后面的讀請求自然會從資料庫中讀取新值然后回填快取,
方案二
Redis里的資料總是不過期,但是有個背景更新任務(“定時執行的代碼” 或者 “被佇列驅動的代碼)讀取db,把最新的資料塞給Redis,這種做法將Redis看作是“存盤”,訪問者不知道背后的實際資料源,只知道Redis是唯一可以取的資料的地方,當實際資料源更新時,背景更新任務來將資料更新到Redis,這時還是會存在Redis和實際資料源不一致的問題,如果是定時任務,最長的不一致時長就是更新任務的執行間隔;如果是用類似于佇列的方式來更新,那么不一致時間取決于佇列產生和消費的延遲,常用的佇列(或等價物)有Redis(怎么還是Redis),Kafka,AMQ,RMQ,binglog,log檔案,阿里的canal等,
注意,沒有所謂的最佳解決方案,針對不同的業務場景我們自主選擇不同的方案,不大可能達到十全十美
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/210522.html
標籤:其他
上一篇:初入Django框架
下一篇:Qt 拖水平滑塊slider改變數字設定框spin box值 改變spin box值水平滑塊slider自動變換 獲取當前值 設定為一半
