0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

架構師居然這么設計DB+緩存

jf_ro2CN3Fa ? 來源:樓仔 ? 作者:樓仔 ? 2022-10-10 16:24 ? 次閱讀

來源:樓仔

不好的方案

1. 先寫 MySQL,再寫 Redis

2. 先寫 Redis,再寫 MySQL

3. 先刪除 Redis,再寫 MySQL

好的方案

5. 先寫 MySQL,再刪除 Redis

6. 先寫 MySQL,通過 Binlog,異步更新 Redis

幾種方案比較

大家好,這個問題很早之前我就遇到過,但是一直沒有仔細去研究,上個月看了極客的課程,有一篇文章專門有過講解,所以感覺有必要單獨出一篇。

我直接先拋一下結論:在滿足實時性的條件下,不存在兩者完全保存一致的方案,只有最終一致性方案。 根據(jù)網(wǎng)上的眾多解決方案,總結出 6 種,直接看目錄:

05019796-3750-11ed-ba43-dac502259ad0.png

不好的方案

1. 先寫 MySQL,再寫 Redis

0512eda2-3750-11ed-ba43-dac502259ad0.png

圖解說明:

這是一副時序圖,描述請求的先后調(diào)用順序;

橘黃色的線是請求 A,黑色的線是請求 B;

橘黃色的文字,是 MySQL 和 Redis 最終不一致的數(shù)據(jù);

數(shù)據(jù)是從 10 更新為 11;

后面所有的圖,都是這個含義,不再贅述。

請求 A、B 都是先寫 MySQL,然后再寫 Redis,在高并發(fā)情況下,如果請求 A 在寫 Redis 時卡了一會,請求 B 已經(jīng)依次完成數(shù)據(jù)的更新,就會出現(xiàn)圖中的問題。

這個圖已經(jīng)畫的很清晰了,我就不用再去啰嗦了吧,不過這里有個前提,就是對于讀請求,先去讀 Redis,如果沒有,再去讀 DB,但是讀請求不會再回寫 Redis。 大白話說一下,就是讀請求不會更新 Redis。

2. 先寫 Redis,再寫 MySQL

052753dc-3750-11ed-ba43-dac502259ad0.png

同“先寫 MySQL,再寫 Redis”,看圖可秒懂。

3. 先刪除 Redis,再寫 MySQL

這幅圖和上面有些不一樣,前面的請求 A 和 B 都是更新請求,這里的請求 A 是更新請求,但是請求 B 是讀請求,且請求 B 的讀請求會回寫 Redis。

05385380-3750-11ed-ba43-dac502259ad0.png

請求 A 先刪除緩存,可能因為卡頓,數(shù)據(jù)一直沒有更新到 MySQL,導致兩者數(shù)據(jù)不一致。

這種情況出現(xiàn)的概率比較大,因為請求 A 更新 MySQL 可能耗時會比較長,而請求 B 的前兩步都是查詢,會非??臁?/strong>

好的方案

4. 先刪除 Redis,再寫 MySQL,再刪除 Redis

對于“先刪除 Redis,再寫 MySQL”,如果要解決最后的不一致問題,其實再對 Redis 重新刪除即可,這個也是大家常說的“緩存雙刪”。

054369a0-3750-11ed-ba43-dac502259ad0.png

為了便于大家看圖,對于藍色的文字,“刪除緩存 10”必須在“回寫緩存10”后面,那如何才能保證一定是在后面呢?網(wǎng)上給出的第一個方案是,讓請求 A 的最后一次刪除,等待 500ms。

對于這種方案,看看就行,反正我是不會用,太 Low 了,風險也不可控。

那有沒有更好的方案呢,我建議異步串行化刪除,即刪除請求入隊列

054eca98-3750-11ed-ba43-dac502259ad0.png

異步刪除對線上業(yè)務無影響,串行化處理保障并發(fā)情況下正確刪除。

如果雙刪失敗怎么辦,網(wǎng)上有給 Redis 加一個緩存過期時間的方案,這個不敢茍同。個人建議整個重試機制,可以借助消息隊列的重試機制,也可以自己整個表,記錄重試次數(shù) ,方法很多。

簡單小結一下:

“緩存雙刪”不要用無腦的 sleep 500 ms;

通過消息隊列的異步&串行,實現(xiàn)最后一次緩存刪除;

緩存刪除失敗,增加重試機制。

5. 先寫 MySQL,再刪除 Redis

055dbc60-3750-11ed-ba43-dac502259ad0.png

對于上面這種情況,對于第一次查詢,請求 B 查詢的數(shù)據(jù)是 10,但是 MySQL 的數(shù)據(jù)是 11,只存在這一次不一致的情況,對于不是強一致性要求的業(yè)務,可以容忍。 (那什么情況下不能容忍呢,比如秒殺業(yè)務、庫存服務等。)

當請求 B 進行第二次查詢時,因為沒有命中 Redis,會重新查一次 DB,然后再回寫到 Reids。

056a71da-3750-11ed-ba43-dac502259ad0.png

這里需要滿足 2 個條件:

緩存剛好自動失效;

請求 B 從數(shù)據(jù)庫查出 10,回寫緩存的耗時,比請求 A 寫數(shù)據(jù)庫,并且刪除緩存的還長。

對于第二個條件,我們都知道更新 DB 肯定比查詢耗時要長,所以出現(xiàn)這個情況的概率很小,同時滿足上述條件的情況更小。

6. 先寫 MySQL,通過 Binlog,異步更新 Redis

這種方案,主要是監(jiān)聽 MySQL 的 Binlog,然后通過異步的方式,將數(shù)據(jù)更新到 Redis,這種方案有個前提,查詢的請求,不會回寫 Redis。

057bab30-3750-11ed-ba43-dac502259ad0.png

這個方案,會保證 MySQL 和 Redis 的最終一致性,但是如果中途請求 B 需要查詢數(shù)據(jù),如果緩存無數(shù)據(jù),就直接查 DB;如果緩存有數(shù)據(jù),查詢的數(shù)據(jù)也會存在不一致的情況。

所以這個方案,是實現(xiàn)最終一致性的終極解決方案,但是不能保證實時性。

幾種方案比較

我們對比上面討論的 6 種方案:

先寫 Redis,再寫 MySQL

這種方案,我肯定不會用 ,萬一 DB 掛了,你把數(shù)據(jù)寫到緩存,DB 無數(shù)據(jù),這個是災難性的;

我之前也見同學這么用過,如果寫 DB 失敗,對 Redis 進行逆操作,那如果逆操作失敗呢,是不是還要搞個重試?

先寫 MySQL,再寫 Redis

對于并發(fā)量、一致性要求不高的項目,很多就是這么用的 ,我之前也經(jīng)常這么搞,但是不建議這么做;

當 Redis 瞬間不可用的情況,需要報警出來,然后線下處理。

先刪除 Redis,再寫 MySQL

這種方式,我還真沒用過,直接忽略吧。

先刪除 Redis,再寫 MySQL,再刪除 Redis

這種方式雖然可行,但是感覺好復雜 ,還要搞個消息隊列去異步刪除 Redis。

先寫 MySQL,再刪除 Redis

比較推薦這種方式 ,刪除 Redis 如果失敗,可以再多重試幾次,否則報警出來;

這個方案,是實時性中最好的方案,在一些高并發(fā)場景中,推薦這種。

先寫 MySQL,通過 Binlog,異步更新 Redis

對于異地容災、數(shù)據(jù)匯總等,建議會用這種方式 ,比如 binlog + kafka,數(shù)據(jù)的一致性也可以達到秒級;

純粹的高并發(fā)場景,不建議用這種方案,比如搶購、秒殺等。

個人結論:

實時一致性方案 :采用“先寫 MySQL,再刪除 Redis”的策略,這種情況雖然也會存在兩者不一致,但是需要滿足的條件有點苛刻,所以是滿足實時性條件下,能盡量滿足一致性的最優(yōu)解。

最終一致性方案 :采用“先寫 MySQL,通過 Binlog,異步更新 Redis”,可以通過 Binlog,結合消息隊列異步更新 Redis,是最終一致性的最優(yōu)解。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 架構
    +關注

    關注

    1

    文章

    505

    瀏覽量

    25427
  • MySQL
    +關注

    關注

    1

    文章

    794

    瀏覽量

    26359
  • Redis
    +關注

    關注

    0

    文章

    370

    瀏覽量

    10813
  • binlog
    +關注

    關注

    0

    文章

    6

    瀏覽量

    1243

原文標題:從美團挖來的架構師居然這么設計DB+緩存,真的長見識了!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    聊聊緩存擊穿的解決方法

    緩存擊穿,Redis中的某個熱點key不存在或者過期,但是此時有大量的用戶訪問該key。比如xxx直播間優(yōu)惠券搶購、xxx商品活動,這時候大量用戶會在某個時間點一同訪問該熱點事件。但是可能
    的頭像 發(fā)表于 10-23 13:54 ?67次閱讀

    什么是CPU緩存?它有哪些作用?

    CPU緩存(Cache Memory)是計算機系統(tǒng)中一個至關重要的組成部分,它位于CPU與內(nèi)存之間,作為兩者之間的臨時存儲器。CPU緩存的主要作用是減少CPU訪問內(nèi)存所需的時間,從而提高系統(tǒng)的整體性能。以下將詳細闡述CPU緩存
    的頭像 發(fā)表于 08-22 14:54 ?1749次閱讀

    中級自動駕駛架構師應該學習哪些知識

    隨著自動駕駛技術的成熟,對系統(tǒng)架構師的需求逐漸增加。自動駕駛系統(tǒng)架構師負責設計整個系統(tǒng)的結構、組件、接口和數(shù)據(jù)流;需要協(xié)調(diào)不同領域的專業(yè)知識,確保系統(tǒng)的可靠性、安全性和性能??傊詣玉{駛系統(tǒng)架構師
    的頭像 發(fā)表于 06-20 21:47 ?223次閱讀

    初級自動駕駛架構師應該學習哪些知識

    隨著自動駕駛技術的成熟,對系統(tǒng)架構師的需求逐漸增加。自動駕駛系統(tǒng)架構師負責設計整個系統(tǒng)的結構、組件、接口和數(shù)據(jù)流;需要協(xié)調(diào)不同領域的專業(yè)知識,確保系統(tǒng)的可靠性、安全性和性能??傊?,自動駕駛系統(tǒng)架構師
    的頭像 發(fā)表于 06-20 21:45 ?222次閱讀

    如何選擇合適的本地緩存?

    小編最近在使用系統(tǒng)的時候,發(fā)現(xiàn)盡管應用已經(jīng)使用了 redis 緩存提高查詢效率,但是仍然有進一步優(yōu)化的空間,于是想到了比分布式緩存性能更好的本地緩存,因此對領域內(nèi)常用的本地緩存進行了一
    的頭像 發(fā)表于 01-18 11:19 ?779次閱讀
    如何選擇合適的本地<b class='flag-5'>緩存</b>?

    Redis緩存預熱+緩存雪崩+緩存擊穿+緩存穿透要點簡析

    緩存預熱就是系統(tǒng)上線后,提前將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。
    的頭像 發(fā)表于 12-25 09:41 ?785次閱讀
    Redis<b class='flag-5'>緩存</b>預熱+<b class='flag-5'>緩存</b>雪崩+<b class='flag-5'>緩存</b>擊穿+<b class='flag-5'>緩存</b>穿透要點簡析

    作為射頻工程,你真的會用“dB”?

    作為射頻工程,你真的會用“dB”?
    的頭像 發(fā)表于 12-06 14:51 ?502次閱讀
    作為射頻工程<b class='flag-5'>師</b>,你真的會用“<b class='flag-5'>dB</b>”?

    CPU Cache是如何保證緩存一致性的?

    我們介紹`CPU Cache`的組織架構及其進行**讀操作**時的尋址方式,但是緩存不僅僅只有讀操作,還有 **寫操作** ,這會帶來一個新的問題
    的頭像 發(fā)表于 12-04 15:05 ?1199次閱讀
    CPU Cache是如何保證<b class='flag-5'>緩存</b>一致性的?

    mybatis一級緩存和二級緩存的原理

    MyBatis是一種輕量級的持久化框架,它提供了一級緩存和二級緩存的機制來優(yōu)化數(shù)據(jù)庫操作性能。一級緩存是默認開啟的,而二級緩存需要手動配置啟用。 一、一級
    的頭像 發(fā)表于 12-03 11:55 ?1006次閱讀

    恩智浦首席車載網(wǎng)絡架構師開講:CAN SIC與CAN XL芯片如何賦能未來汽車網(wǎng)絡?

    zh 汽車正朝向智能化和電氣化快速演進,這也帶來了車載網(wǎng)絡架構的變遷——正在從功能域轉變?yōu)閰^(qū)域架構,實現(xiàn)更高的帶寬、更小的時延以及更多的功能。這種變化也給汽車行業(yè)帶來了諸多挑戰(zhàn)。 為了應對這些挑戰(zhàn)
    的頭像 發(fā)表于 12-01 09:15 ?1107次閱讀
    恩智浦首席車載網(wǎng)絡<b class='flag-5'>架構師</b>開講:CAN SIC與CAN XL芯片如何賦能未來汽車網(wǎng)絡?

    【急招】嵌入式軟件架構師,年80w內(nèi)可談!

    嵌入式linux平臺,架構經(jīng)驗,5年以上經(jīng)驗 工作地點:北京市海淀區(qū) 薪酬:年80內(nèi)可談?12月份需要到崗?
    發(fā)表于 11-23 10:13

    優(yōu)秀的架構師是怎樣繪制系統(tǒng)架構藍圖的?

    模型是對客觀存在的抽象,例如著名的物理學公式 E=mc2,就是質量能量轉換的物理規(guī)律的數(shù)學模型。除了物理學公式以外,還有一些東西也是模型,比如地圖是對地理空間的建模;機械裝置、電子電路、建筑設計的各種圖紙是對物理實體的建模。而軟件,也可以通過各種圖進行建模。
    的頭像 發(fā)表于 11-20 16:13 ?386次閱讀
    優(yōu)秀的<b class='flag-5'>架構師</b>是怎樣繪制系統(tǒng)<b class='flag-5'>架構</b>藍圖的?

    什么是-3dB?ATA-1000系列寬帶放大器最大帶寬是多少?

    在功率放大器的相關選型參數(shù)中,我們常常會發(fā)現(xiàn)這么一個內(nèi)容:-3dB。對于我們常說的電路帶寬或系統(tǒng)帶寬,指的是增益為-3dB時的頻率點,那什么是-3dB帶寬?且為什么選-3
    的頭像 發(fā)表于 11-20 15:45 ?1341次閱讀
    什么是-3<b class='flag-5'>dB</b>?ATA-1000系列寬帶放大器最大帶寬是多少?

    Socket緩存如何影響TCP的性能

    一直以來我們都知道socket的緩存會對tcp性能產(chǎn)生影響,也有無數(shù)文章告訴我們應該調(diào)大socke緩存。但是究竟調(diào)多大?什么時候調(diào)?有哪些手段調(diào)?具體影響究竟如何?這些問題似乎也沒有人真正說明
    的頭像 發(fā)表于 11-09 10:13 ?531次閱讀

    db是什么意思

    會看到dB這個參數(shù),如LDO的電壓抑制比是55dB,麥克風的最大聲壓級為125dB…… 先來看看歷史由來: dB展開應寫為decibel,其中“deci-”為十分之一,而“bel”則是
    的頭像 發(fā)表于 11-01 16:22 ?1.1w次閱讀
    <b class='flag-5'>db</b>是什么意思