一、為什么不直接更新緩存?
無論寫數據庫和寫緩存,哪個操作在前,都不要更新緩存;
因為更新數據庫和更新緩存是兩個獨立的階段,並發場景下不同線程的兩個階段,可能發生交叉,最終導致數據庫和緩存長時間不一致,這種長時間的不一致是不能容忍的。
不一致時長:緩存過期時間,或下一次更新。
二、如何理解Cache Aside Pattern?
這是一種公認的經典緩存一致性處理模式,采用先寫庫,再刪緩存的操作。這種無鎖的方案,只能保證並發的前提下,盡可能的降低不一致的概率。這也是AP策略下的一種BASE方案
- 理想狀態:因為並發場景下,這兩個階段之間其他線程會讀到舊的緩存數據,但經過這個極短的間隙后,最終會再次一致。
不一致時長:寫數據庫后刪除緩存前。
- 讀卡頓問題:極端一點,在三個以上並發時,兩寫一讀:
1.線程1完成了寫數據庫和刪緩存;
2.此時由於緩存被刪除,線程2只能讀數據庫,讀完后寫入緩存前,線程2卡頓了。
3.線程3又完成了一次寫和刪。
4.線程2才將其從數據庫讀到的數據寫入緩存
5.此時緩存和數據庫就不一致了。
不一致時長:緩存過期時間,或下一次更新。
三、延時雙刪策略解決了哪些極端場景下的數據不一致問題?
針對讀卡頓問題,在Cache Aside Pattern的基礎上,延時地再刪一次緩存,能有效的縮短緩存不一致時長。
可以采用MQ延時消息,或其他異步手段。
延時的時長設定,通常1、2秒就能覆蓋絕大多數場景。
不一致時長:延時時長。
四、注意
-
即便用【Cache Aside Pattern + 延時雙刪】這種組合,仍不能保證100%的緩存一致性。
-
但通常,使用緩存的場景本身就不要求強一致性。
-
實在要保證緩存和數據庫的強一致性,最好的辦法就是分布式鎖,但是並發性能較差,除非場景要求強一致性,且能容忍較低的並發性才用鎖。