上回程序員阿旺為了提升數據訪問的性能,引入 Redis 作為 MySQL 緩存層,但是這件事情并不是那么簡單,因為還要考慮 Redis 和 MySQL 雙寫一致性的問題。阿旺經過一番周折,最終選用了「先更新數據庫,再刪緩存」的策略,原因是這個策略即使在并發(fā)讀寫時,也能最大程度保證數據一致性。聰明的阿旺還搞了個兜底的方案,就是給緩存加上了過期時間。本以為就這樣不會在出現數據一致性的問題,結果將功能上線后,老板還是收到用戶的投訴「說自己明明更新了數據,但是數據要過一段時間才生效」,客戶接受不了。老板轉告給了阿旺,阿旺得知又有 Bug 就更慌了,立馬就登錄服務器去排查問題,查看日志后得知了原因?!赶雀聰祿?, 再刪除緩存」其實是兩個操作,這次客戶投訴的問題就在于,在刪除緩存(第二個操作)的時候失敗了,導致緩存中的數據是舊值,而數據庫是最新值。好在之前給緩存加上了過期時間,所以才會出現客戶說的過一段時間才更新生效的現象,假設如果沒有這個過期時間的兜底,那后續(xù)的請求讀到的就會一直是緩存中的舊數據,這樣問題就更大了。所以新的問題來了,如何保證「先更新數據庫 ,再刪除緩存」這兩個操作能執(zhí)行成功?阿旺分析出問題后,慌慌張張的向老板匯報了問題。老板知道事情后,又給了阿旺幾天來解決這個問題,畫餅的事情這次沒有再提了。
阿旺會用什么方式來解決這個問題呢?
老板畫的餅事情,能否兌現給阿旺呢?
如何保證兩個操作都能執(zhí)行成功?
這次用戶的投訴是因為在刪除緩存(第二個操作)的時候失敗了,導致緩存還是舊值,而數據庫是最新值,造成數據庫和緩存數據不一致的問題,會對敏感業(yè)務造成影響。舉個例子,來說明下。應用要把數據 X 的值從 1 更新為 2,先成功更新了數據庫,然后在 Redis 緩存中刪除 X 的緩存,但是這個操作卻失敗了,這個時候數據庫中 X 的新值為 2,Redis 中的 X 的緩存值為 1,出現了數據庫和緩存數據不一致的問題。那么,后續(xù)有訪問數據 X 的請求,會先在 Redis 中查詢,因為緩存并沒有 誒刪除,所以會緩存命中,但是讀到的卻是舊值 1。其實不管是先操作數據庫,還是先操作緩存,只要第二個操作失敗都會出現數據一致的問題。問題原因知道了,該怎么解決呢?有兩種方法: