緩存與數據庫雙寫一致最佳解決方案分析

寫在最前面

在大型互聯網應用當中如果你的應用引入了緩存機制果港,那么有一個大前提就是你的業(yè)務場景上必須得接受數據的新鮮度上有可能會有一定時間的延遲。刪除緩存失敗是一個極小概率事件,且在不能保證所有操作100%成功的幾率下征峦,采用JOB補償的機制是目前比較成熟的解決方案于颖。
大并發(fā)量寫請求的應用呆贿,不可能去實時寫DB,基本都采用隊列+消息異步寫DB的機制森渐,不然會有大量的并發(fā)問題


緩存機制介紹

如今利用緩存機制來提高查詢效率已被廣泛用在各大生產環(huán)境做入,查詢數據的一般流程如下所示

使用緩存提高查詢效率
  1. 如果數據在緩存里邊有,則直接從緩存取數據返回同衣。
  2. 如果緩存中沒有想要的數據竟块,則先去查詢數據庫,然后將數據庫查出來的數據寫到緩存中再返回

沒有更新數據的情況下耐齐,數據庫和緩存的數據是保持一致的浪秘;但是當要執(zhí)行數據的更新操作的時候,數據庫和緩存的數據就會出現不一致的情況

因此埠况,為了解決數據不一致的問題耸携,需要在更新數據庫的時候,對緩存做一些額外的操作询枚,有以下幾種方案

  1. 先刪緩存违帆,再更新數據庫
  2. 先更新數據庫,再刪緩存
  3. 緩存延時雙刪金蜀,更新前先刪除緩存刷后,然后更新數據,再延時刪除緩存
  4. 監(jiān)聽MySQL binlog進行緩存更新

之所以緩存不采取更新操作而是直接刪除是因為:高并發(fā)環(huán)境下渊抄,無論是先操作數據庫還是后操作數據庫而言尝胆,如果加上更新緩存,那就更加容易導致數據庫與緩存數據不一致問題护桦。(刪除緩存直接且簡單很多)

先刪除緩存含衔,再更新數據庫

該方案在線程A進行數據更新操作,線程B進行查詢操作時,有可能出現下面的情況導致數據不一致:

  1. 線程A刪除緩存
  2. 線程B查詢數據贪染,發(fā)現緩存數據不存在
  3. 線程B查詢數據庫缓呛,得到舊值,寫入緩存
  4. 線程A將新值更新到數據庫

這樣一來杭隙,緩存中的數據仍然是舊值

如果線程B執(zhí)行的是更新操作哟绊,線程B查詢得到的是舊值,A更新到數據庫新值痰憎,然后B基于舊值計算寫入了計算后的值票髓,A的更新操作被抹去了,這種情況下屬于更新數據事務原子性問題铣耘,需要用分布式鎖來解決洽沟。

先更新數據庫,再刪除緩存

當緩存失效時蜗细,線程B原子性被破壞時會出現不一致問題:

  1. 緩存失效了
  2. 線程B從數據庫讀取舊值
  3. 線程A從數據庫讀取舊值
  4. 線程B將新值更新到數據庫
  5. 線程B刪除緩存
  6. 線程A將舊值寫入緩存

這種情況概率很低裆操,實際上數據庫的寫操作會比讀操作慢得多,讀操作必需在寫操作前進入數據庫操作鳄乏,而又要晚于寫操作更新緩存跷车,這種情況下只需要線程B延時刪除緩存就好。另外在數據庫主從同步的情況下橱野,延時刪除還能防止數據更新還未從主數據庫同步到從數據庫的情況朽缴。

延時雙刪

延時雙刪即先刪除緩存,然后更新數據水援,再延時n ms后刪除緩存密强,這個我認為作用和更新數據庫再刪除緩存的策略幾乎是等同的(歡迎討論)

之所以設計為延時雙刪的目的在于當最后一次延時刪除緩存失敗的情況發(fā)生,至少一致性策略只會退化成先刪緩存再更新數據的策略蜗元。

刪除緩存失敗這種事情個人認為在生產環(huán)境緩存高可用的情況下幾乎不會出現或渤,且這種情況如果發(fā)生了,不如考慮一下重試機制奕扣。

異步更新緩存(基于訂閱binlog的同步機制)

通過異步更新緩存將緩存與數據庫的一致性同步從業(yè)務中獨立出來統一處理薪鹦,保證數據一致性

整體技術思路:

  1. 讀Redis:熱數據基本都在Redis
  2. 寫MySQL:增刪改都是操作MySQL
  3. 更新Redis數據:訂閱MySQ的數據操作記錄binlog,來更新到Redis

數據操作分為兩大部分:

  • 全量更新(將全部數據一次性寫入redis)
  • 增量更新(實時更新)

這樣一旦MySQL中產生了新的寫入、更新、刪除等操作汇恤,就可以把binlog相關的消息通過消息隊列推送至Redis月帝,Redis再根據binlog中的記錄灾常,對Redis進行更新。

這種同步機制類似于MySQL的主從備份機制,可以結合使用阿里的canal對MySQL的binlog進行訂閱。

總結

綜上所述端考,異步更新緩存雅潭、更新后延遲刪與延遲雙刪都是不錯的一致性解決方案,但除了異步更新緩存却特,其余兩個方案都會對業(yè)務線的代碼有侵入性扶供。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市核偿,隨后出現的幾起案子诚欠,更是在濱河造成了極大的恐慌,老刑警劉巖漾岳,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異粉寞,居然都是意外死亡尼荆,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門唧垦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捅儒,“玉大人,你說我怎么就攤上這事振亮∏苫梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵坊秸,是天一觀的道長麸祷。 經常有香客問我,道長褒搔,這世上最難降的妖魔是什么阶牍? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮星瘾,結果婚禮上走孽,老公的妹妹穿的比我還像新娘。我一直安慰自己琳状,他們只是感情好磕瓷,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著念逞,像睡著了一般困食。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肮柜,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天陷舅,我揣著相機與錄音,去河邊找鬼审洞。 笑死莱睁,一個胖子當著我的面吹牛待讳,可吹牛的內容都是我干的。 我是一名探鬼主播仰剿,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼创淡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了南吮?” 一聲冷哼從身側響起琳彩,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎部凑,沒想到半個月后露乏,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡涂邀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年瘟仿,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片比勉。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡劳较,死狀恐怖,靈堂內的尸體忽然破棺而出浩聋,到底是詐尸還是另有隱情观蜗,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布衣洁,位于F島的核電站墓捻,受9級特大地震影響,放射性物質發(fā)生泄漏闸与。R本人自食惡果不足惜毙替,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望践樱。 院中可真熱鬧厂画,春花似錦、人聲如沸拷邢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞭稼。三九已至忽洛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間环肘,已是汗流浹背欲虚。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留悔雹,地道東北人复哆。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓欣喧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親梯找。 傳聞我的和親對象是個殘疾皇子唆阿,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355