快取與資料庫一致性問題

2021-10-14 01:21:05 字數 2545 閱讀 4985

業務場景

抓拍到的人臉需要推送到第三方系統,但不是所有的網點都需要推送資訊。也就是要做到不同的網點可以根據配置來決定是否推送,前端頁面需要有推送配置功能,手動配置後,把配置的推送資訊儲存到資料庫。抓拍到人臉**後,讀取配置的推送資訊,再判斷是否需要推送。由於網點多抓拍的人臉資料量較大,推送資訊配置後不常修改,也就是讀多寫少,所以考慮把配置的推送資訊儲存資料庫後再儲存乙份至redis中。

實現方案

快取和資料庫的資料一致性有多種實現方式,各實現方式可以自行了解,以及他們各自的優缺點。在此使用的是先更新資料庫,再刪除快取的方式,為了防止刪除快取失敗,增加了重試機制

,同時為了保證資料的最終一致性,給快取增加了過期時間。

**如下:

儲存推送配置資訊

可以看到**中是先刪除已有配置,接著批量新增新的配置,最後刪除快取。

刪除快取

刪除快取增加了重試機制,防止刪除失敗,出現資料不一致問題。

接著,讀取推送配置資訊:

可以看到,當第一次讀取資料的時候先從快取中查詢,當不存在時再查詢資料庫,資料庫也不存在的時候,生成預設的推送配置資訊,更新到

redis

中,然後返回。

更新快取操作

給快取增加了過期時間

問題現象

在一次自測時發現,有乙個網點配置的不推送,竟然接收到推送。

於是查詢redis中的資料,確實是推送配置

再次檢視資料庫

發現資料庫中的結果是正確的,不推送。

因此出現了資料庫與快取中的資料不一致現象

問題排查

首先檢視執行日誌,看是不是快取刪除失敗導致的。結果沒有發現刪除失敗以及重試刪除的日誌,也沒有redis異常連線的任何資訊。

然後測試其他網點配置,多次測試驗證也沒有出現快取與資料庫不一致的現象。因此判定是乙個偶現的情況,根據以往經驗,偶現的問題或有可能出現問題的**,在現場一定會再次出現。繼續排查

最後只能檢視**,是哪個環節有問題。

最後發現可能跟資料庫的事務有關,在儲存推送配置的方法上有@transactional

註解,有該註解的方法在執行時會被事務***攔截,在方法前設定是否自動提交為false,方法執行後提交事務。也就是推送配置在方法執行完成後資料才會被儲存到資料庫中。仔細看方法內的實現,刪除redis快取是在方法內執行的。

本來的實現方式是:

先更新資料庫,再刪除快取,現在卻是先刪除快取,再更新資料庫。因此在刪除快取後,提交事務之前這短暫的時間如果有查詢推送資訊的操作,則會查詢到舊資料,並更新到快取,當提交事務後,就會出現快取與資料庫不一致的現象

debug驗證

在刪除快取之後的**打上斷點,此時事務還未提交,檢視

redis,

發現redis

中的快取已被刪除,此時查詢推送配置資訊,會把舊資料重新更新的

redis

中,然後放開斷點繼續執行**,就出現了快取與資料庫不一致的現象。

解決方案

找到問題的原因後,解決方式就很簡單了。就是在資料庫的事務提交之後,再執行刪除快取的操作就可以。有多種實現方式,下面介紹三種:

把運算元據庫的操作單獨放到乙個事務方法中

使用程式設計式事務的方式,在同乙個方法中就可以完成

使用transactionsynchronizationmanager在事務提交之後操作

總結

在資料庫的事務方法內部最好不要執行遠端呼叫,因為遠端呼叫成功後事務提交失敗,則遠端呼叫不能回滾,即使都執行成功也要考慮遠端呼叫的結果與事務**中的結果是否有業務關聯,否則可能會出現資料不一致的問題,並且排查非常困難。

盡可能的讓遠端呼叫在事務開始之前或結束之後執行。

redis快取與資料庫一致性問題

不一致產生的原因 我們在使用redis過程中,通常會這樣做 先讀取快取,如果快取不存在,則讀取資料庫。偽 如下 object stuobj new object public stu getstufromcache string key return stu 寫資料庫的偽 如下 public voi...

資料庫和快取一致性問題

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

快取與資料庫一致性問題深度剖析

背景 背景 在併發讀寫的時候,資料明明已經成功寫入資料庫之中,但是我們從快取中讀出的資料還是以前的舊資料,開始以為是瀏覽器快取的問題,清了瀏覽器快取之後還是沒有。那可能是資料還沒有同步到快取中,按照 邏輯這有點不太可能呀!雖然不可能,那我們還是等等看吧。等了一段時間之後,資料顯示的還是舊資料。還是不...