持久化資料 快取資料雙寫一致性

2021-09-13 18:25:32 字數 1252 閱讀 7242

快取中資料更新一般有兩個入口,

快取未過期,資料庫資料有變動主動更新至快取;

關於資料一致性

需要將髒資料的存在時間範圍放在可控範圍內;

併發:因為無事務,無法保證雙寫的一致性;

多資料來源:如果拿著乙份資料分別向持久層和快取執行執行更新,在時序無法保證時會出現交叉覆蓋的情況;

互斥:快取的初始化(查詢資料+set快取)需要保證原子性,並且初始化和快取的淘汰需要互斥,否則併發下交叉執行會有舊資料覆蓋情況;

多資料來源的描述實際也是因為無事務+併發造成的;

事務、併發:

保證互斥:

更新快取or淘汰快取(刪除快取)

根據上述的通過保證唯一資料來源來避免問題,應該採用淘汰快取,然後快取通過從持久化層獲取資料完成初始化;

如果採用更新快取,無論更新快取和更新資料庫前後順序怎麼排列;

即無論是「更新快取+更新資料庫」還是「更新資料庫+更新快取」都會有以下問題;

事務:

使用淘汰快取,而不是更新快取;

- 如果不考慮上述快取操作異常情況;

- 更新快取時如果快取未超時,此場景是無問題的;

- 場景:如果快取資料是有效期的或者其他操作,導致在執行「更新資料庫」之前 原快取資料過期,此時有其它執行緒訪問快取資料並觸發了快取初始化流程:

a_查詢持久化資料+b_將查詢結果set至快取;那麼就會有乙個細節上的問題了:

- 如果上述兩個環節a&b都在當前執行緒的c_淘汰快取這個環節之前完成,那就不會有問題,最後結果是再次淘汰快取,保證了一致性;

- 如果上述兩個環節a&b交叉在c之間,即執行時序是a-c-b,那麼上述的c_淘汰快取操作就無意義了,還是會導致不一致;

- 解決方案:

- 因為快取的初始化是有同步鎖控制的,如果將快取淘汰操作也加入同乙個同步鎖控制內,就可以避免上述a-c-b的問題;並且不會造成額外影響;

邏輯上是符合常理的;並且資料持久化完成之後「更新快取」操作失敗的兜底機制和保證快取的互斥性是需要關注的核心問題;

上述的資料持久化都是在講的概念,實際上如果存在讀寫分離,從庫從主庫同步資料需要一定的時間,即使在保證上述邏輯正常執行的情況下,

也需要考慮,當新資料成功持久化至主庫之後、從庫同步資料之前,有訪問資料的請求落在從庫上,讀到的還是舊資料,仍然會造成髒資料;

訂閱資料庫binlog日誌,在資料完成同步的時候重新發起「淘汰快取」操作,並輔以訊息重試機制保證執行;

快取雙寫一致性方案

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解析。於...

Redis快取與資料庫雙寫一致性

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取呢?又或者是先刪除快取,再更新資料庫呢?其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解析...

redis 雙寫一致性

首先,快取由於其高併發和高效能的特性,已經在專案中被廣泛使用。在讀取快取方面,大家沒啥疑問,都是按照下圖的流程來進行業務操作。但是在更新快取方面,對於更新完資料庫,是更新快取呢,還是刪除快取。又或者是先刪除快取,再更新資料庫,其實大家存在很大的爭議。目前沒有一篇全面的部落格,對這幾種方案進行解析。於...