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

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

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

架構(gòu)師居然這么設(shè)計(jì)DB+緩存

jf_ro2CN3Fa ? 來(lái)源:樓仔 ? 作者:樓仔 ? 2022-10-10 16:24 ? 次閱讀

來(lái)源:樓仔

不好的方案

1. 先寫 MySQL,再寫 Redis

2. 先寫 Redis,再寫 MySQL

3. 先刪除 Redis,再寫 MySQL

好的方案

5. 先寫 MySQL,再刪除 Redis

6. 先寫 MySQL,通過(guò) Binlog,異步更新 Redis

幾種方案比較

大家好,這個(gè)問(wèn)題很早之前我就遇到過(guò),但是一直沒(méi)有仔細(xì)去研究,上個(gè)月看了極客的課程,有一篇文章專門有過(guò)講解,所以感覺(jué)有必要單獨(dú)出一篇。

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

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

不好的方案

1. 先寫 MySQL,再寫 Redis

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

圖解說(shuō)明:

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

橘黃色的線是請(qǐng)求 A,黑色的線是請(qǐng)求 B;

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

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

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

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

這個(gè)圖已經(jīng)畫(huà)的很清晰了,我就不用再去啰嗦了吧,不過(guò)這里有個(gè)前提,就是對(duì)于讀請(qǐng)求,先去讀 Redis,如果沒(méi)有,再去讀 DB,但是讀請(qǐng)求不會(huì)再回寫 Redis。 大白話說(shuō)一下,就是讀請(qǐng)求不會(huì)更新 Redis。

2. 先寫 Redis,再寫 MySQL

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

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

3. 先刪除 Redis,再寫 MySQL

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

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

請(qǐng)求 A 先刪除緩存,可能因?yàn)榭D,數(shù)據(jù)一直沒(méi)有更新到 MySQL,導(dǎo)致兩者數(shù)據(jù)不一致。

這種情況出現(xiàn)的概率比較大,因?yàn)檎?qǐng)求 A 更新 MySQL 可能耗時(shí)會(huì)比較長(zhǎng),而請(qǐng)求 B 的前兩步都是查詢,會(huì)非常快。

好的方案

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

對(duì)于“先刪除 Redis,再寫 MySQL”,如果要解決最后的不一致問(wèn)題,其實(shí)再對(duì) Redis 重新刪除即可,這個(gè)也是大家常說(shuō)的“緩存雙刪”。

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

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

對(duì)于這種方案,看看就行,反正我是不會(huì)用,太 Low 了,風(fēng)險(xiǎn)也不可控。

那有沒(méi)有更好的方案呢,我建議異步串行化刪除,即刪除請(qǐng)求入隊(duì)列

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

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

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

簡(jiǎn)單小結(jié)一下:

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

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

緩存刪除失敗,增加重試機(jī)制。

5. 先寫 MySQL,再刪除 Redis

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

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

當(dāng)請(qǐng)求 B 進(jìn)行第二次查詢時(shí),因?yàn)闆](méi)有命中 Redis,會(huì)重新查一次 DB,然后再回寫到 Reids。

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

這里需要滿足 2 個(gè)條件:

緩存剛好自動(dòng)失效;

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

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

6. 先寫 MySQL,通過(guò) Binlog,異步更新 Redis

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

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

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

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

幾種方案比較

我們對(duì)比上面討論的 6 種方案:

先寫 Redis,再寫 MySQL

這種方案,我肯定不會(huì)用 ,萬(wàn)一 DB 掛了,你把數(shù)據(jù)寫到緩存,DB 無(wú)數(shù)據(jù),這個(gè)是災(zāi)難性的;

我之前也見(jiàn)同學(xué)這么用過(guò),如果寫 DB 失敗,對(duì) Redis 進(jìn)行逆操作,那如果逆操作失敗呢,是不是還要搞個(gè)重試?

先寫 MySQL,再寫 Redis

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

當(dāng) Redis 瞬間不可用的情況,需要報(bào)警出來(lái),然后線下處理。

先刪除 Redis,再寫 MySQL

這種方式,我還真沒(méi)用過(guò),直接忽略吧。

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

這種方式雖然可行,但是感覺(jué)好復(fù)雜 ,還要搞個(gè)消息隊(duì)列去異步刪除 Redis。

先寫 MySQL,再刪除 Redis

比較推薦這種方式 ,刪除 Redis 如果失敗,可以再多重試幾次,否則報(bào)警出來(lái);

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

先寫 MySQL,通過(guò) Binlog,異步更新 Redis

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

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

個(gè)人結(jié)論:

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

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

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

    關(guān)注

    1

    文章

    516

    瀏覽量

    25493
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    816

    瀏覽量

    26614
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    376

    瀏覽量

    10887
  • binlog
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    1252

原文標(biāo)題:從美團(tuán)挖來(lái)的架構(gòu)師居然這么設(shè)計(jì)DB+緩存,真的長(zhǎng)見(jiàn)識(shí)了!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    HTTP緩存頭的使用 本地緩存與遠(yuǎn)程緩存的區(qū)別

    HTTP緩存頭是一組HTTP響應(yīng)頭,它們控制瀏覽器和中間代理服務(wù)器如何緩存網(wǎng)頁(yè)內(nèi)容。合理使用HTTP緩存頭可以顯著提高網(wǎng)站的加載速度和性能,減少服務(wù)器的負(fù)載。 1. HTTP緩存頭概述
    的頭像 發(fā)表于 12-18 09:41 ?122次閱讀

    Web緩存的類型及功能分析

    隨著互聯(lián)網(wǎng)的迅速發(fā)展,用戶對(duì)網(wǎng)絡(luò)內(nèi)容的訪問(wèn)需求日益增長(zhǎng)。為了提高用戶體驗(yàn)和降低服務(wù)器負(fù)擔(dān),Web緩存技術(shù)應(yīng)運(yùn)而生。Web緩存通過(guò)存儲(chǔ)重復(fù)請(qǐng)求的數(shù)據(jù),減少了對(duì)原始服務(wù)器的訪問(wèn)次數(shù),從而加快了數(shù)據(jù)傳輸
    的頭像 發(fā)表于 12-18 09:35 ?196次閱讀

    緩存技術(shù)在軟件開(kāi)發(fā)中的應(yīng)用

    在現(xiàn)代軟件開(kāi)發(fā)中,隨著數(shù)據(jù)量的爆炸性增長(zhǎng)和用戶對(duì)響應(yīng)速度的高要求,緩存技術(shù)成為了提升系統(tǒng)性能的重要手段。緩存技術(shù)通過(guò)將數(shù)據(jù)存儲(chǔ)在離用戶更近的位置,減少數(shù)據(jù)訪問(wèn)延遲,提高數(shù)據(jù)處理速度,從而優(yōu)化
    的頭像 發(fā)表于 12-18 09:32 ?251次閱讀

    什么是緩存(Cache)及其作用

    緩存(Cache)是一種高速存儲(chǔ)器,用于臨時(shí)存儲(chǔ)數(shù)據(jù),以便快速訪問(wèn)。在計(jì)算機(jī)系統(tǒng)中,緩存的作用是減少處理器訪問(wèn)主存儲(chǔ)器(如隨機(jī)存取存儲(chǔ)器RAM)所需的時(shí)間。 緩存(Cache)概述 緩存
    的頭像 發(fā)表于 12-18 09:28 ?876次閱讀

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

    Guava cache是Google開(kāi)發(fā)的Guava工具包中一套完善的JVM本地緩存框架,底層實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)類似于ConcurrentHashMap,但是進(jìn)行了更多的能力拓展,包括緩存過(guò)期時(shí)間設(shè)置、緩存容量設(shè)置、多種淘汰策略、
    的頭像 發(fā)表于 11-17 14:24 ?345次閱讀
    <b class='flag-5'>緩存</b>之美——如何選擇合適的本地<b class='flag-5'>緩存</b>?

    智算中心網(wǎng)絡(luò)交換機(jī)需要什么樣的緩存架構(gòu)

    場(chǎng)景時(shí),并非緩存越大越好,過(guò)大的緩存會(huì)導(dǎo)致更長(zhǎng)的隊(duì)列、更高的時(shí)延和抖動(dòng)、更高的成本,所以不能簡(jiǎn)單地去擴(kuò)大緩存,交換機(jī)避免丟包所需的緩存與此帶寬延遲積BDP直接相關(guān),借助于帶寬時(shí)延積BD
    的頭像 發(fā)表于 11-14 16:53 ?495次閱讀
    智算中心網(wǎng)絡(luò)交換機(jī)需要什么樣的<b class='flag-5'>緩存</b><b class='flag-5'>架構(gòu)</b>

    TPA3251能足功率輸出嗎?

    請(qǐng)問(wèn)TI的工程,TPA3251芯片的管腳和3116一樣細(xì),而且輸出B,C都只有一個(gè)管腳,這么細(xì)的管腳居然能輸出175w的功率,請(qǐng)問(wèn)TI是如何做到的,能足功率輸出嗎?
    發(fā)表于 10-30 07:43

    聊聊緩存擊穿的解決方法

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

    一位架構(gòu)師的自述:在尚未踏入的世界成為你自己

    這是我參與創(chuàng)作者計(jì)劃的第1篇文章 ? ? 我叫艾佳,工作經(jīng)驗(yàn)14年,編程經(jīng)驗(yàn)30年。 我來(lái)自智能平臺(tái)部,負(fù)責(zé)標(biāo)簽平臺(tái)、標(biāo)簽圈人、標(biāo)簽選品、EasyData、算法數(shù)據(jù)流的架構(gòu)工作。 致力于批量
    的頭像 發(fā)表于 09-23 15:25 ?367次閱讀
    一位<b class='flag-5'>架構(gòu)師</b>的自述:在尚未踏入的世界成為你自己

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

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

    JFE150 100Hz處的噪聲為什么偏差這么大?

    @100Hz和-131.6dB@1KHz。但是實(shí)際電路噪聲測(cè)試的結(jié)果如圖3所示,我用的測(cè)量噪聲儀器是安捷倫35670A。實(shí)際測(cè)試電路噪聲在100Hz處為-122.6dB,在1KHz處為-131dB。不明白為什么100Hz處的噪聲
    發(fā)表于 08-01 06:13

    中級(jí)自動(dòng)駕駛架構(gòu)師應(yīng)該學(xué)習(xí)哪些知識(shí)

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

    初級(jí)自動(dòng)駕駛架構(gòu)師應(yīng)該學(xué)習(xí)哪些知識(shí)

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

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

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

    labview怎么清除串口緩存的數(shù)據(jù)

    LabVIEW 是一款功能強(qiáng)大的圖形化編程軟件,常用于控制、監(jiān)測(cè)和數(shù)據(jù)采集等應(yīng)用。當(dāng)我們使用串口進(jìn)行數(shù)據(jù)通信時(shí),有時(shí)會(huì)遇到串口緩存的數(shù)據(jù)無(wú)法及時(shí)清除或清除不徹底的情況。解決這個(gè)問(wèn)題的方法有多種,下面
    的頭像 發(fā)表于 01-08 11:30 ?3891次閱讀