如何保證緩存與數(shù)據(jù)庫雙寫時的數(shù)據(jù)一致性?
點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”
回復(fù)”學(xué)習(xí)資料“獲取學(xué)習(xí)寶典
來源:https://www.jianshu.com/p/a8eb1412471f
| 背景
第1級:訂單數(shù)據(jù)和支付流水?dāng)?shù)據(jù);這兩塊數(shù)據(jù)對實(shí)時性和精確性要求很高,所以不添加任何緩存,讀寫操作將直接操作數(shù)據(jù)庫。 第2級:用戶相關(guān)數(shù)據(jù);這些數(shù)據(jù)和用戶相關(guān),具有讀多寫少的特征,所以我們使用redis進(jìn)行緩存。 第3級:支付配置信息;這些數(shù)據(jù)和用戶無關(guān),具有數(shù)據(jù)量小,頻繁讀,幾乎不修改的特征,所以我們使用本地內(nèi)存進(jìn)行緩存。
接下來就討論一下關(guān)于保證緩存和數(shù)據(jù)庫雙寫時的數(shù)據(jù)一致性。
| 解決方案
那么我們這里列出來所有策略,并且討論他們優(yōu)劣性。
先更新數(shù)據(jù)庫,后更新緩存 先更新數(shù)據(jù)庫,后刪除緩存 先更新緩存,后更新數(shù)據(jù)庫 先刪除緩存,后更新數(shù)據(jù)庫
| 先更新數(shù)據(jù)庫,后更新緩存
| 先更新緩存,后更新數(shù)據(jù)庫
|先刪除緩存,后更新數(shù)據(jù)庫
該方案也會出問題,具體出現(xiàn)的原因如下。

此時來了兩個請求,請求 A(更新操作) 和請求 B(查詢操作)。
請求 A 會先刪除 Redis 中的數(shù)據(jù),然后去數(shù)據(jù)庫進(jìn)行更新操作。 此時請求 B 看到 Redis 中的數(shù)據(jù)時空的,會去數(shù)據(jù)庫中查詢該值,補(bǔ)錄到 Redis 中。 但是此時請求 A 并沒有更新成功,或者事務(wù)還未提交。
那么這時候就會產(chǎn)生數(shù)據(jù)庫和 Redis 數(shù)據(jù)不一致的問題。如何解決呢?其實(shí)最簡單的解決辦法就是延時雙刪的策略。

但是上述的保證事務(wù)提交完以后再進(jìn)行刪除緩存還有一個問題,就是如果你使用的是 Mysql 的讀寫分離的架構(gòu)的話,那么其實(shí)主從同步之間也會有時間差。

此時來了兩個請求,請求 A(更新操作) 和請求 B(查詢操作)。
請求 A 更新操作,刪除了 Redis。 請求主庫進(jìn)行更新操作,主庫與從庫進(jìn)行同步數(shù)據(jù)的操作。 請 B 查詢操作,發(fā)現(xiàn) Redis 中沒有數(shù)據(jù)。 去從庫中拿去數(shù)據(jù)。 此時同步數(shù)據(jù)還未完成,拿到的數(shù)據(jù)是舊數(shù)據(jù)。
此時的解決辦法就是如果是對 Redis 進(jìn)行填充數(shù)據(jù)的查詢數(shù)據(jù)庫操作,那么就強(qiáng)制將其指向主庫進(jìn)行查詢。

| 先更新數(shù)據(jù)庫,后刪除緩存
問題:這一種情況也會出現(xiàn)問題,比如更新數(shù)據(jù)庫成功了,但是在刪除緩存的階段出錯了沒有刪除成功,那么此時再讀取緩存的時候每次都是錯誤的數(shù)據(jù)了。

此時解決方案就是利用消息隊(duì)列進(jìn)行刪除的補(bǔ)償。具體的業(yè)務(wù)邏輯用語言描述如下:
請求 A 先對數(shù)據(jù)庫進(jìn)行更新操作。 在對 Redis 進(jìn)行刪除操作的時候發(fā)現(xiàn)報錯,刪除失敗。 此時將Redis 的 key 作為消息體發(fā)送到消息隊(duì)列中。 系統(tǒng)接收到消息隊(duì)列發(fā)送的消息后再次對 Redis 進(jìn)行刪除操作。
但是這個方案會有一個缺點(diǎn)就是會對業(yè)務(wù)代碼造成大量的侵入,深深的耦合在一起,所以這時會有一個優(yōu)化的方案,我們知道對 Mysql 數(shù)據(jù)庫更新操作后再 binlog 日志中我們都能夠找到相應(yīng)的操作,那么我們可以訂閱 Mysql 數(shù)據(jù)庫的 binlog 日志對緩存進(jìn)行操作。

利用訂閱binlog 刪除緩存
最后一種方案我們最后討論了利用訂閱 binlog 日志進(jìn)行搭建獨(dú)立系統(tǒng)操作 Redis,這樣的缺點(diǎn)其實(shí)就是增加了系統(tǒng)復(fù)雜度。
其實(shí)每一次的選擇都需要我們對于我們的業(yè)務(wù)進(jìn)行評估來選擇,沒有一種技術(shù)是對于所有業(yè)務(wù)都通用的。沒有最好的,只有最適合我們的。
后臺回復(fù)?學(xué)習(xí)資料?領(lǐng)取學(xué)習(xí)視頻

