資料庫和快取一致性

2021-09-17 22:34:57 字數 1741 閱讀 1426

今天程式過程中突然想到了乙個問題,怎麼保證redis快取和mysql資料庫中的資料相同(一致性)。即在更新資料時怎樣保證資料庫和redis快取始終相同。從理論上講,給快取設定過期時間是保證最終一致性的解決方案。這種方案下,所有寫操作以資料庫為準,對快取做最大努力即可。下面介紹的是不依賴於給快取設定過期時間的更新資料的方案。

首先必須明確一點,所有的資料都是必須以資料庫持久化的資料為主,快取是為了加快獲取資料的方式,所以無論怎樣保證一致性都必須保證資料庫中的資料是邏輯正確的。

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

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

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

如下的不一致的情況:

執行緒a更新了資料庫;

執行緒b更新了資料庫;

執行緒b更新了快取;

執行緒a更新了快取;

如圖,可能是網路原因或者是更新資料大小寫入操作耗時等問題,導致先更新的最後才寫入到快取,從而導致 快取與資料庫不一致。此場景不易被消除,所以此中方式不可取。

業務場景不可取原因:

若存在大量且快速的更新操作,那麼還未來得及讀取快取,快取資料就又被更新了,這樣就有很多更新是不必要的,浪費效能。

如下的不一致的情況:

執行緒a先刪除快取;

執行緒b讀取快取,讀取不到;

執行緒b到資料庫讀取到舊值;

執行緒b讀取到的舊值寫入快取;

執行緒a更新資料庫;

同樣在這種情況下,若是採用了讀寫分離的策略,則有如下不一致的情況:

執行緒a先刪除快取;

執行緒a更新資料到寫資料庫;

執行緒b讀取快取,獲取不到;

執行緒b從讀資料庫讀取獲取到舊值;

執行緒b把舊值寫入快取;

資料庫完成主從複製,讀資料庫更新了值

如下的不一致的情況:

快取剛好失效;

執行緒b讀取快取無效;

執行緒b讀取資料庫舊值;;

執行緒a更新資料庫;

執行緒a刪除快取;

執行緒b把舊值寫入快取;

這種情況相對來說少一些,因為一般寫資料庫的操作更加耗時,並且還得執行緒a一次完成兩步,所以此方案是更容易接受的。

基本的過程分為三步:

先刪除快取;

更新資料庫;

過一定時間後再刪除快取一次(1~2s)

存在的問題:

這是一次同步的操作的話,這個1~2s會大大的降低系統的效能。所以可以就愛能第二步的刪除做乙個非同步刪除。

但是如果第二次刪除失敗呢??

更新資料庫資料;

資料庫會將操作資訊寫入binlog日誌當中;

訂閱程式提取出所需要的資料以及key;

另起一段非業務**,獲得該資訊;

嘗試刪除快取操作,發現刪除失敗;

將這些資訊傳送至訊息佇列;

重新從訊息佇列中獲得該資料,重試操作;

備註說明:上述的訂閱binlog程式在mysql中有現成的中介軟體叫canal,可以完成訂閱binlog日誌的功能。另外,重試機制,博主是採用的是訊息佇列的方式。如果對一致性要求不是很高,直接在程式中另起乙個執行緒,每隔一段時間去重試即可,這些大家可以靈活自由發揮,只是提供乙個思路。

資料庫和快取一致性方案

redis儲存快取,mysql儲存資料。快取進行有效期設定。但是更新mysql,不會更新快取。這樣導致快取和資料庫的一致性問題比較長 mysql更新後,進行更新redis快取。查詢的時候先查詢redis快取,如果沒有快取,只查詢資料庫進行更新快取 快取和資料庫不一致性的時間短 cache aside...

資料庫和快取一致性推薦方式

資料儲存在資料庫中,為了加快業務訪問的速度,我們將資料庫中的一些資料放在快取中,那麼問題來了,如何確保db和快取中資料的一致性呢?我們列出了5種方法,大家都了解一下,然後根據業務自己選擇。獲取快取邏輯 使用過定時器,定時重新整理redis中的快取。db更新資料邏輯 更新資料不用考慮快取中的資料,直接...

資料庫和快取一致性問題

前言 快取一致性是指業務在引入分布式快取系統後,業務對資料的更新除了要更新儲存以外還需要同時更新快取,對兩個系統進行資料更新就要先解決分布式系統中的隔離性和原子性難題。目前大多數業務在引入分布式快取後都是通過犧牲小概率的一致性來保障業務效能,因為要在業務層嚴格保障資料的一致性,代價非常高,業務引入分...