您現在的位置是:首頁 > 運動

Mysql和Redis資料如何保持一致

由 京東雲企業管家 發表于 運動2023-01-15
簡介只更新快取,由快取自己非同步更新資料庫(Write Behind Cache Pattern)這種方式性詳單于是業務只操作更新快取,再由快取非同步去更新資料庫,例如:如上圖所示,其可能的執行流程順序為:客戶端1 觸發更新資料A的邏輯客戶端2

怎麼保證redis和資料庫資料一致

先闡明一下Mysql和Redis的關係:Mysql是資料庫,用來持久化資料,一定程度上保證資料的可靠性;Redis是用來當快取,用來提升資料訪問的效能。

Mysql和Redis資料如何保持一致

關於如何保證Mysql和Redis中的資料一致(即快取一致性問題),這是一個非常經典的問題。

使用過快取的人都應該知道,在實際應用場景中,要想實時刻保證快取和資料庫中的資料一樣,很難做到。

基本上都是儘可能讓他們的資料在絕大部分時間內保持一致,並保證最終是一致的。

快取不一致是如何產生的

如果資料一直沒有變更,那麼就不會出現快取不一致的問題。

通常快取不一致是發生在資料有變更的時候。 因為每次資料變更你需要同時操作資料庫和快取,而他們又屬於不同的系統,無法做到同時操作成功或失敗,總會有一個時間差。在併發讀寫的時候可能就會出現快取不一致的問題(理論上透過分散式事務可以保證這一點,不過實際上基本上很少有人這麼做)。

雖然沒辦法在資料有變更時,保證快取和資料庫強一致,但對快取的更新還是有一定設計方法的,遵循這些設計方法,能夠讓這個不一致的影響時間和影響範圍最小化。

快取更新的幾種設計

快取更新的設計方法大概有以下四種:

先刪除快取,再更新資料庫(這種方法在併發下最容易出現長時間的髒資料,不可取)

先更新資料庫,刪除快取(Cache Aside Pattern)

只更新快取,由快取自己同步更新資料庫(Read/Write Through Pattern)

只更新快取,由快取自己非同步更新資料庫(Write Behind Cache Pattern)

接下來詳細介紹一些這四種設計方法

先刪除快取,再更新資料庫

這種方法在併發讀寫的情況下容易出現快取不一致的問題

Mysql和Redis資料如何保持一致

如上圖所示,其可能的執行流程順序為:

客戶端1 觸發更新資料A的邏輯

客戶端2 觸發查詢資料A的邏輯

客戶端1 刪除快取中資料A

客戶端2 查詢快取中資料A,未命中

客戶端2 從資料庫查詢資料A,並更新到快取中

客戶端1 更新資料庫中資料A

可見,最後快取中的資料A跟資料庫中的資料A是不一致的,快取中的資料A是舊的髒資料。

因此一般不建議使用這種方式。

先更新資料庫,再讓快取失效

這種方法在併發讀寫的情況下,也可能會出現短暫快取不一致的問題

Mysql和Redis資料如何保持一致

如上圖所示,其可能執行的流程順序為:

客戶端1 觸發更新資料A的邏輯

客戶端2 觸發查詢資料A的邏輯

客戶端3 觸發查詢資料A的邏輯

客戶端1 更新資料庫中資料A

客戶端2 查詢快取中資料A,命中返回(舊資料)

客戶端1 讓快取中資料A失效

客戶端3 查詢快取中資料A,未命中

客戶端3 查詢資料庫中資料A,並更新到快取中

可見,最後快取中的資料A和資料庫中的資料A是一致的,理論上可能會出現一小段時間資料不一致,不過這種機率也比較低,大部分的業務也不會有太大的問題。

只更新快取,由快取自己同步更新資料庫(Read/Write Through Pattern)

這種方法相當於是業務只更新快取,再由快取去同步更新資料庫。 一個Write Through的 例子如下:

Mysql和Redis資料如何保持一致

如上圖所示,其可能執行的流程順序為:

客戶端1 觸發更新資料A的邏輯

客戶端2 觸發查詢資料A的邏輯

客戶端1 更新快取中資料A,快取同步更新資料庫中資料A,再返回結果

客戶端2 查詢快取中資料A,命中返回

Read Through 和 WriteThrough 的流程類似,只是在客戶端查詢資料A時,如果快取中資料A失效了(過期或被驅逐淘汰),則快取會同步去資料庫中查詢資料A,並快取起來,再返回給客戶端

這種方式快取不一致的機率極低,只不過需要對快取進行專門的改造。

只更新快取,由快取自己非同步更新資料庫(Write Behind Cache Pattern)

這種方式性詳單于是業務只操作更新快取,再由快取非同步去更新資料庫,例如:

Mysql和Redis資料如何保持一致

如上圖所示,其可能的執行流程順序為:

客戶端1 觸發更新資料A的邏輯

客戶端2 觸發查詢資料A的邏輯

客戶端1 更新快取中的資料A,返回

客戶端2 查詢快取中的資料A,命中返回

快取非同步更新資料A到資料庫中

這種方式的優勢是讀寫的效能都非常好,基本上只要操作完記憶體後就返回給客戶端了,但是其是非強一致性,存在丟失資料的情況。

如果在快取非同步將資料更新到資料庫中時,快取服務掛了,此時未更新到資料庫中的資料就丟失了。

總結

上面講到的幾種快取更新的設計方式,都是前人總結出來的經驗,這些方式或多或少都有一些弊端,並不完美,實際上也很難有完美的設計。 大家在做系統設計的時候,也不要去追求完美,要有一些取捨,找到一種最適合自己業務場景的方式就行

作者:追光者

推薦文章