4 種策略讓 MySQL 和 Redis 數據保持一致
先闡明一下 MySQL 和 Redis 的關係:MySQL 是數據庫,用來持久化數據,一定程度上保證數據的可靠性;Redis 是用來當緩存,用來提升數據訪問的性能。
關於如何保證 MySQL 和 Redis 中的數據一致(即緩存一致性問題),這是一個非常經典的問題。
使用過緩存的人都應該知道,在實際應用場景中,要想實時刻保證緩存和數據庫中的數據一樣,很難做到。
基本上都是儘可能讓他們的數據在絕大部分時間內保持一致,並保證最終是一致的。
1、緩存不一致是如何產生的
如果數據一直沒有變更,那麼就不會出現緩存不一致的問題。
通常緩存不一致是發生在數據有變更的時候。因爲每次數據變更你需要同時操作數據庫和緩存,而他們又屬於不同的系統,無法做到同時操作成功或失敗,總會有一個時間差。在併發讀寫的時候可能就會出現緩存不一致的問題(理論上通過分佈式事務可以保證這一點,不過實際上基本上很少有人這麼做)。
雖然沒辦法在數據有變更時,保證緩存和數據庫強一致,但對緩存的更新還是有一定設計方法的,遵循這些設計方法,能夠讓這個不一致的影響時間和影響範圍最小化。
2、緩存更新的幾種設計
緩存更新的設計方法大概有以下四種:
-
先刪除緩存,再更新數據庫(這種方法在併發下最容易出現長時間的髒數據,不可取)
-
先更新數據庫,刪除緩存(Cache Aside Pattern)
-
只更新緩存,由緩存自己同步更新數據庫(Read/Write Through Pattern)
-
只更新緩存,由緩存自己異步更新數據庫(Write Behind Cache Pattern)
接下來詳細介紹一些這四種設計方法
2.1 先刪除緩存,再更新數據庫
這種方法在併發讀寫的情況下容易出現緩存不一致的問題
如上圖所示,其可能的執行流程順序爲:
-
客戶端 1 觸發更新數據 A 的邏輯
-
客戶端 2 觸發查詢數據 A 的邏輯
-
客戶端 1 刪除緩存中數據 A
-
客戶端 2 查詢緩存中數據 A,未命中
-
客戶端 2 從數據庫查詢數據 A,並更新到緩存中
-
客戶端 1 更新數據庫中數據 A
可見,最後緩存中的數據 A 跟數據庫中的數據 A 是不一致的,緩存中的數據 A 是舊的髒數據。
因此一般不建議使用這種方式。
2.2 先更新數據庫,再讓緩存失效
這種方法在併發讀寫的情況下,也可能會出現短暫緩存不一致的問題
如上圖所示,其可能執行的流程順序爲:
-
客戶端 1 觸發更新數據 A 的邏輯
-
客戶端 2 觸發查詢數據 A 的邏輯
-
客戶端 3 觸發查詢數據 A 的邏輯
-
客戶端 1 更新數據庫中數據 A
-
客戶端 2 查詢緩存中數據 A,命中返回(舊數據)
-
客戶端 1 讓緩存中數據 A 失效
-
客戶端 3 查詢緩存中數據 A,未命中
-
客戶端 3 查詢數據庫中數據 A,並更新到緩存中
可見,最後緩存中的數據 A 和數據庫中的數據 A 是一致的,理論上可能會出現一小段時間數據不一致,不過這種概率也比較低,大部分的業務也不會有太大的問題。
2.3 只更新緩存,由緩存自己同步更新數據庫(Read/Write Through Pattern)
這種方法相當於是業務只更新緩存,再由緩存去同步更新數據庫。一個 Write Through 的 例子如下:
如上圖所示,其可能執行的流程順序爲:
-
客戶端 1 觸發更新數據 A 的邏輯
-
客戶端 2 觸發查詢數據 A 的邏輯
-
客戶端 1 更新緩存中數據 A,緩存同步更新數據庫中數據 A,再返回結果
-
客戶端 2 查詢緩存中數據 A,命中返回
Read Through 和 WriteThrough 的流程類似,只是在客戶端查詢數據 A 時,如果緩存中數據 A 失效了(過期或被驅逐淘汰),則緩存會同步去數據庫中查詢數據 A,並緩存起來,再返回給客戶端。
這種方式緩存不一致的概率極低,只不過需要對緩存進行專門的改造。
2.4 只更新緩存,由緩存自己異步更新數據庫(Write Behind Cache Pattern)
這種方式性詳單于是業務只操作更新緩存,再由緩存異步去更新數據庫,例如:
如上圖所示,其可能的執行流程順序爲:
-
客戶端 1 觸發更新數據 A 的邏輯
-
客戶端 2 觸發查詢數據 A 的邏輯
-
客戶端 1 更新緩存中的數據 A,返回
-
客戶端 2 查詢緩存中的數據 A,命中返回
-
緩存異步更新數據 A 到數據庫中
這種方式的優勢是讀寫的性能都非常好,基本上只要操作完內存後就返回給客戶端了,但是其是非強一致性,存在丟失數據的情況。
如果在緩存異步將數據更新到數據庫中時,緩存服務掛了,此時未更新到數據庫中的數據就丟失了。
總結
上面講到的幾種緩存更新的設計方式,都是前人總結出來的經驗,這些方式或多或少都有一些弊端,並不完美,實際上也很難有完美的設計。大家在做系統設計的時候,也不要去追求完美,要有一些取捨,找到一種最適合自己業務場景的方式就行。
轉自:追光者,
鏈接:developer.jdcloud.com/article/2776
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/HUauYXddf9AGa3UjcuqHYg