<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何保證緩存與數(shù)據(jù)庫(kù)雙寫時(shí)的數(shù)據(jù)一致性?

          共 2407字,需瀏覽 5分鐘

           ·

          2022-02-25 12:15

          上一篇:別瞎寫工具類了,Spring自帶的這些他不香麼?


          如何保證緩存與數(shù)據(jù)庫(kù)雙寫時(shí)的數(shù)據(jù)一致性?

          在做系統(tǒng)優(yōu)化時(shí),想到了將數(shù)據(jù)進(jìn)行分級(jí)存儲(chǔ)的思路。因?yàn)樵谙到y(tǒng)中會(huì)存在一些數(shù)據(jù),有些數(shù)據(jù)的實(shí)時(shí)性要求不高,比如一些配置信息。基本上配置了很久才會(huì)變一次。而有一些數(shù)據(jù)實(shí)時(shí)性要求非常高,比如訂單和流水的數(shù)據(jù)。所以這里根據(jù)數(shù)據(jù)要求實(shí)時(shí)性不同將數(shù)據(jù)分為三級(jí)。
          • 第1級(jí):訂單數(shù)據(jù)和支付流水?dāng)?shù)據(jù);這兩塊數(shù)據(jù)對(duì)實(shí)時(shí)性和精確性要求很高,所以不添加任何緩存,讀寫操作將直接操作數(shù)據(jù)庫(kù)。
          • 第2級(jí):用戶相關(guān)數(shù)據(jù);這些數(shù)據(jù)和用戶相關(guān),具有讀多寫少的特征,所以我們使用redis進(jìn)行緩存。
          • 第3級(jí):支付配置信息;這些數(shù)據(jù)和用戶無(wú)關(guān),具有數(shù)據(jù)量小,頻繁讀,幾乎不修改的特征,所以我們使用本地內(nèi)存進(jìn)行緩存。

          但是只要使用到緩存,無(wú)論是本地內(nèi)存做緩存還是使用 redis 做緩存,那么就會(huì)存在數(shù)據(jù)同步的問(wèn)題,因?yàn)榕渲眯畔⒕彺嬖趦?nèi)存中,而內(nèi)存時(shí)無(wú)法感知到數(shù)據(jù)在數(shù)據(jù)庫(kù)的修改。這樣就會(huì)造成數(shù)據(jù)庫(kù)中的數(shù)據(jù)與緩存中數(shù)據(jù)不一致的問(wèn)題。接下來(lái)就討論一下關(guān)于保證緩存和數(shù)據(jù)庫(kù)雙寫時(shí)的數(shù)據(jù)一致性。

          解決方案

          那么我們這里列出來(lái)所有策略,并且討論他們優(yōu)劣性。

          1. 先更新數(shù)據(jù)庫(kù),后更新緩存

          2. 先更新數(shù)據(jù)庫(kù),后刪除緩存

          3. 先更新緩存,后更新數(shù)據(jù)庫(kù)

          4. 先刪除緩存,后更新數(shù)據(jù)庫(kù)

          先更新數(shù)據(jù)庫(kù),后更新緩存

          這種場(chǎng)景一般是沒(méi)有人使用的,主要原因是在更新緩存那一步,為什么呢?因?yàn)橛械臉I(yè)務(wù)需求緩存中存在的值并不是直接從數(shù)據(jù)庫(kù)中查出來(lái)的,有的是需要經(jīng)過(guò)一系列計(jì)算來(lái)的緩存值,那么這時(shí)候后你要更新緩存的話其實(shí)代價(jià)是很高的。如果此時(shí)有大量的對(duì)數(shù)據(jù)庫(kù)進(jìn)行寫數(shù)據(jù)的請(qǐng)求,但是讀請(qǐng)求并不多,那么此時(shí)如果每次寫請(qǐng)求都更新一下緩存,那么性能損耗是非常大的。
          舉個(gè)例子比如在數(shù)據(jù)庫(kù)中有一個(gè)值為 1 的值,此時(shí)我們有 10 個(gè)請(qǐng)求對(duì)其每次加一的操作,但是這期間并沒(méi)有讀操作進(jìn)來(lái),如果用了先更新數(shù)據(jù)庫(kù)的辦法,那么此時(shí)就會(huì)有十個(gè)請(qǐng)求對(duì)緩存進(jìn)行更新,會(huì)有大量的冷數(shù)據(jù)產(chǎn)生,如果我們不更新緩存而是刪除緩存,那么在有讀請(qǐng)求來(lái)的時(shí)候那么就會(huì)只更新緩存一次。

          先更新緩存,后更新數(shù)據(jù)庫(kù)

          這一種情況應(yīng)該不需要我們考慮了吧,和第一種情況是一樣的。

          先刪除緩存,后更新數(shù)據(jù)庫(kù)

          該方案也會(huì)出問(wèn)題,具體出現(xiàn)的原因如下。

          此時(shí)來(lái)了兩個(gè)請(qǐng)求,請(qǐng)求 A(更新操作) 和請(qǐng)求 B(查詢操作)
          1. 請(qǐng)求 A 會(huì)先刪除 Redis 中的數(shù)據(jù),然后去數(shù)據(jù)庫(kù)進(jìn)行更新操作
          2. 此時(shí)請(qǐng)求 B 看到 Redis 中的數(shù)據(jù)時(shí)空的,會(huì)去數(shù)據(jù)庫(kù)中查詢?cè)撝担a(bǔ)錄到 Redis 中
          3. 但是此時(shí)請(qǐng)求 A 并沒(méi)有更新成功,或者事務(wù)還未提交
          那么這時(shí)候就會(huì)產(chǎn)生數(shù)據(jù)庫(kù)和 Redis 數(shù)據(jù)不一致的問(wèn)題。如何解決呢?其實(shí)最簡(jiǎn)單的解決辦法就是延時(shí)雙刪的策略。
          但是上述的保證事務(wù)提交完以后再進(jìn)行刪除緩存還有一個(gè)問(wèn)題,就是如果你使用的是 Mysql 的讀寫分離的架構(gòu)的話,那么其實(shí)主從同步之間也會(huì)有時(shí)間差。
          此時(shí)來(lái)了兩個(gè)請(qǐng)求,請(qǐng)求 A(更新操作) 和請(qǐng)求 B(查詢操作)
          1. 請(qǐng)求 A 更新操作,刪除了 Redis
          2. 請(qǐng)求主庫(kù)進(jìn)行更新操作,主庫(kù)與從庫(kù)進(jìn)行同步數(shù)據(jù)的操作
          3. 請(qǐng) B 查詢操作,發(fā)現(xiàn) Redis 中沒(méi)有數(shù)據(jù)
          4. 去從庫(kù)中拿去數(shù)據(jù)
          5. 此時(shí)同步數(shù)據(jù)還未完成,拿到的數(shù)據(jù)是舊數(shù)據(jù)
          此時(shí)的解決辦法就是如果是對(duì) Redis 進(jìn)行填充數(shù)據(jù)的查詢數(shù)據(jù)庫(kù)操作,那么就強(qiáng)制將其指向主庫(kù)進(jìn)行查詢。

          先更新數(shù)據(jù)庫(kù),后刪除緩存

          問(wèn)題:這一種情況也會(huì)出現(xiàn)問(wèn)題,比如更新數(shù)據(jù)庫(kù)成功了,但是在刪除緩存的階段出錯(cuò)了沒(méi)有刪除成功,那么此時(shí)再讀取緩存的時(shí)候每次都是錯(cuò)誤的數(shù)據(jù)了。
          此時(shí)解決方案就是利用消息隊(duì)列進(jìn)行刪除的補(bǔ)償。具體的業(yè)務(wù)邏輯用語(yǔ)言描述如下:
          1. 請(qǐng)求 A 先對(duì)數(shù)據(jù)庫(kù)進(jìn)行更新操作
          2. 在對(duì) Redis 進(jìn)行刪除操作的時(shí)候發(fā)現(xiàn)報(bào)錯(cuò),刪除失敗
          3. 此時(shí)將Redis 的 key 作為消息體發(fā)送到消息隊(duì)列中
          4. 系統(tǒng)接收到消息隊(duì)列發(fā)送的消息后再次對(duì) Redis 進(jìn)行刪除操作
          但是這個(gè)方案會(huì)有一個(gè)缺點(diǎn)就是會(huì)對(duì)業(yè)務(wù)代碼造成大量的侵入,深深的耦合在一起,所以這時(shí)會(huì)有一個(gè)優(yōu)化的方案,我們知道對(duì) Mysql 數(shù)據(jù)庫(kù)更新操作后再 binlog 日志中我們都能夠找到相應(yīng)的操作,那么我們可以訂閱 Mysql 數(shù)據(jù)庫(kù)的 binlog 日志對(duì)緩存進(jìn)行操作。

          總結(jié)

          每種方案各有利弊,比如在第二種先刪除緩存,后更新數(shù)據(jù)庫(kù)這個(gè)方案我們最后討論了要更新 Redis 的時(shí)候強(qiáng)制走主庫(kù)查詢就能解決問(wèn)題,那么這樣的操作會(huì)對(duì)業(yè)務(wù)代碼進(jìn)行大量的侵入,但是不需要增加的系統(tǒng),不需要增加整體的服務(wù)的復(fù)雜度。最后一種方案我們最后討論了利用訂閱 binlog 日志進(jìn)行搭建獨(dú)立系統(tǒng)操作 Redis,這樣的缺點(diǎn)其實(shí)就是增加了系統(tǒng)復(fù)雜度。其實(shí)每一次的選擇都需要我們對(duì)于我們的業(yè)務(wù)進(jìn)行評(píng)估來(lái)選擇,沒(méi)有一種技術(shù)是對(duì)于所有業(yè)務(wù)都通用的。沒(méi)有最好的,只有最適合我們的。
          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。
              · END ·
          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全


          正文結(jié)束


          推薦閱讀 ↓↓↓
          1.心態(tài)崩了!稅前2萬(wàn)4,到手1萬(wàn)4,年終獎(jiǎng)扣稅方式1月1日起施行~

          2.深圳一普通中學(xué)老師工資單曝光,秒殺程序員,網(wǎng)友:敢問(wèn)是哪個(gè)學(xué)校畢業(yè)的?

          3.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4.程序員一般可以從什么平臺(tái)接私活?

          5.清華大學(xué):2021 元宇宙研究報(bào)告!

          6.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

          7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲在线观看免费视频 | 午夜香蕉 | 91精品国产99久久久久久 | 亚洲婷婷国产 | 免费视频二区三区 |