redis 快取更新一致性

2021-10-06 03:18:15 字數 1956 閱讀 6589

當執行寫操作後,需要保證從快取讀取到的資料與資料庫中持久化的資料是一致的,因此需要對快取進行更新。

因為涉及到資料庫和快取兩步操作,難以保證更新的原子性。

在設計更新策略時,我們需要考慮多個方面的問題:

更新快取有兩種方式:

更新快取和更新資料庫有兩種順序:

兩兩組合共有四種更新策略,現在我們逐一進行分析。

併發問題通常由於後開始的執行緒卻先完成操作導致,我們把這種現象稱為「搶跑」。下面我們逐一分析四種策略中「搶跑」帶來的錯誤。

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

若資料庫更新成功,刪除快取操作失敗,則此後讀到的都是快取中過期的資料,造成不一致問題。

可能發生的併發錯誤:

時間執行緒a

執行緒b資料庫快取1

快取失效

v1null

2從資料庫讀取v1

v1null

3更新資料庫

v2null

4刪除快取

v2null

5寫入快取

v2v1

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

同刪除快取策略一樣,若資料庫更新成功快取更新失敗則會造成資料不一致問題。

可能發生的併發錯誤:

時間執行緒a

執行緒b資料庫快取0

v0v0

1更新資料庫為v1

v1v0

2更新資料庫為v2

v2v0

3更新快取為v2

v2v2

4更新快取為v1

v2v1

當兩個寫執行緒發生衝突時,可以通過比較資料版本方式避免執行緒a寫入舊的資料。

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

可能發生的併發錯誤:

時間執行緒a

執行緒b資料庫快取1

刪除快取

v1null

2快取失效

v1null

3從資料庫讀取v1

v1null

4更新資料庫為v2

v2null

5將v1寫入快取

v2v1

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

若快取更新成功資料庫更新失敗, 則此後讀到的都是未持久化的資料。因為快取中的資料是易失的,這種狀態非常危險。

因為資料庫因為鍵約束導致寫入失敗的可能性較高,所以這種策略風險較大。

可能發生的併發錯誤:

時間執行緒a

執行緒b資料庫快取0

v0v0

1更新快取為v1

v0v1

2更新快取為v2

v0v2

3更新資料庫為v2

v2v2

4更新資料庫為v1

v1v2

非同步更新

雙寫更新的邏輯複雜,一致性問題較多。現在我們可以採用訂閱資料庫更新的方式來更新快取。

阿里巴巴開源了mysql資料庫binlog的增量訂閱和消費元件 - canal。

我們可以採用api伺服器只寫入資料庫,而另乙個執行緒訂閱資料庫 binlog 增量進行快取更新的策略。

這種策略存在和先更新資料庫後刪除快取類似的併發問題:

時間讀執行緒

寫執行緒非同步執行緒

資料庫快取

1快取失敗

v1null

2從資料庫讀取v1

v1null

3更新資料庫為v2

v2null

4刪除快取/更新快取

v2null

5寫入快取

v2v1

這個問題同樣可以採用非同步執行緒更新快取,且寫入快取時比較資料版本的方法來解決。

Redis 快取更新一致性

當執行寫操作後,需要保證從快取讀取到的資料與資料庫中持久化的資料是一致的,因此需要對快取進行更新。因為涉及到資料庫和快取兩步操作,難以保證更新的原子性。在設計更新策略時,我們需要考慮多個方面的問題 更新快取有兩種方式 更新快取和更新資料庫有兩種順序 兩兩組合共有四種更新策略,現在我們逐一進行分析。併...

Redis快取一致性

用過redis的應該都清楚,redis作為記憶體快取,只是他查詢快的一大優勢,關係型資料庫只能用作儲存重要資料,或者備份快取的資料,這個時候,不可避免,我們會遇到快取中的資料與關係型資料庫中的資料不一致的情況。出現不一致的現象很常見,如果你是單個使用者肯定不會出現這種情況,如果在多執行緒併發的情況下...

快取一致性

一般應用而言,追求的都是快取的最終一致性。一般的快取系統,都是按照key去快取查詢,如果不存在對應的value,就應該去後端系統查詢 比如db 如果key對應的value是一定不存在的,並且對該key併發請求量很大,就會對後端系統造成很大的壓力。這就叫做快取穿透。引起這個問題的主要原因還是高併發的時...