如何更新快取保證快取和資料庫雙寫一致性?

2022-05-20 15:36:51 字數 2523 閱讀 8325

在專案中快取是經常用到的,為了減少和資料庫的互動,小夥伴們利用快取的思路如下:

我們小夥伴們有沒有考慮到快取更新的問題,小夥伴們肯定會說肯定用過啊,有資料更新時,把快取清空掉就行了啊,下一次訪問的時候服務就會把新值設定到快取中了。這樣不就行了嗎?對的,在一般專案中,這樣的使用就夠了。那麼大家看看在高併發場景下,會有什麼問題?

我們舉例說明,就拿商品的庫存作為快取。那現在我們要更新快取中的庫存值,怎麼進行操作,我們看下面幾個場景:

存在的問題場景:請求a更新值為99,請求b更新值為98

上圖流程:

1)請求a先發起,更新資料庫為99,但還沒有來得及更新快取

2)請求b發起,更新資料庫為98,又更新了快取值為98

3)請求a這時才更新快取的值為99

這樣資料庫的值為98,但快取的值為99,數值不一致。(不推薦)

這個流程跟上面很類似,出現的問題也很類似

1)請求a先更新快取為99,但還沒有來得及更新資料庫

2)請求b更新快取為98,又更新了資料庫為98

3)請求a這時更新資料庫為99

這樣就快取的值為98,資料庫為99導致不一致。(不推薦)

存在的問題場景:請求a更新值為99,請求b獲取值

上圖中請求流程:

1)請求a更新值,先把快取中的值刪除,但還沒有來得及更新資料庫

2)此時請求b過來查詢此值,發現快取中不存在,就到資料庫中查詢

3)請求b在資料庫中獲取到值,在把值設定到快取中。

4)請求a這時才更新資料庫裡面的值為99

這樣就導致了快取和資料庫的不一致問題,快取中的值一直是舊資料。(不推薦)

這個方案也是老外提出的《cache-aside pattern》更新快取的策略。這種策略先保證了源頭的資料一定是正確的。這種策略是不是萬無一失呢,有一種非常特殊的場景

上圖流程:建立中快取突然失效了

1)請求a發起查詢請求,直接到資料庫查詢到100,但還沒有來得及去設定快取

2)請求b更新值,先更新資料庫,在刪除快取

3)請求a這時才設定快取為100

這種情況發生的不一致,是因為快取突然失效了。而且還要保證請求b更新操作 比 請求a的查詢操作還要快;才會導致不一致。這種情況概率會很少。一般要求不高的專案可以採用此方式(推薦)。這種先更新資料庫,再刪除快取的策略中,因為要刪除快取,但如果快取刪除失敗,就會導致資料庫與快取不一致。這個問題怎麼辦?我們正常想到的是利用我們mq中介軟體去實現。

上圖的流程,如果刪除快取失敗,傳送訊息投遞到訊息中介軟體中,進入訊息佇列。也許有小夥伴就會問,如果訊息投遞失敗怎麼辦?我們可以利用訊息中介軟體那邊的保證100%訊息投遞的機制(這個以後再講)。這樣就保證了即使刪除訊息失敗,我們也會重試。

不過這個方案有個問題,就是和我們應用服務的業務**耦合的比較厲害。**業務不清晰。

那我們有沒有別的方案呢,對業務沒有侵入呢?

上圖中其實是利用了mysql的底層機制,binlog日誌進行刪除快取,這樣就不需要和業務關聯,刪除快取服務是獨立的。我們可以利用阿里開源的canal去操作。

這種先更新資料庫,再刪除快取的策略是不是就沒有問題呢?我們來看一下另乙個場景,資料庫的讀寫分離的場景。一般中大型專案都會用到資料庫的讀寫分離。寫請求在乙個庫,讀請求在另乙個庫。讀寫分離會有個問題,就是庫與庫之間會存在資料延遲,因為存在資料同步。

那我們再看一下上面的場景流程,就會有問題,因為請求b更新資料 在乙個庫上面,請求a去讀取資料時是另乙個庫。

1)請求b更新值99,刪除快取

2)請求a查詢值100(讀庫資料還沒有同步),在更新到快取中(值為100)

這樣就導致不一致,這個場景是經常出現的,不是小概率事件。那我們如何處理呢?

請看這一篇:怎麼解決db讀寫分離,導致資料不一致問題?

總結:整個導致不一致的原因就是因為高併發情況下各個請求執行的順序是無法確定的,不知道哪個請求先執行,哪個後執行導致。

樣式快取沒更新 如何保證快取與資料庫的雙寫一致性?

如何保證快取與資料庫的雙寫一致性?你只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫。你只要是雙寫,就一定會有資料一致性的問題,那麼你如何解決一致性問題?一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求 快取 資料庫 必須保持一致性的話,最好不要做這個方案...

如何保證Redis快取和資料庫的雙寫一致性?

在資料庫 快取模式下,當資料庫中的資料需要更新時,快取裡的資料怎麼處理?如何保證快取和資料庫中資料的一致性?常用的解決方案有兩種 其他渣渣的方案這裡不討論 1 先刪除快取,再更新資料庫 2 先更新資料庫,再刪除快取 下面我們就來看一下這兩種方案,看看它們是怎麼保證資料一致性的?理想的流程是這樣的 先...

Redis 如何保證快取與資料庫雙寫時的資料一致性

寫請求來了,要更新資料庫和快取,一前一後更新,就可能導致快取和db中的資料在一段時間內不一致。你只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫,你只要是雙寫,就一定會有資料一致性的問題,那麼你如何解決一致性問題?一般來說,就是如果你的系統不是嚴格要求快取 資料庫必須一致性的話,快取可以稍微的跟資料...