最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解MySQL和Redis如何保證數(shù)據(jù)一致性

 更新時(shí)間:2023年08月18日 09:14:48   作者:馬偉奇  
MySQL與Redis都是常用的數(shù)據(jù)存儲和緩存系統(tǒng),為了提高應(yīng)用程序的性能和可伸縮性,很多應(yīng)用程序?qū)ySQL和Redis一起使用,其中MySQL作為主要的持久存儲,而Redis作為主要的緩存,那么本文就給大家介紹一下MySQL和Redis如何保證數(shù)據(jù)一致性,需要的朋友可以參考下

什么是一致性

“數(shù)據(jù)一致”一般指的是:緩存中有數(shù)據(jù),緩存的數(shù)據(jù)值=數(shù)據(jù)庫中的值。但根據(jù)緩存中是有數(shù)據(jù)為依據(jù),則“一致”可以包含兩種情況:

1)緩存中有數(shù)據(jù),緩存的數(shù)據(jù)值=數(shù)據(jù)庫中的值。

2)緩存中本沒有數(shù)據(jù),數(shù)據(jù)庫中的值=最新值(有請求查詢數(shù)據(jù)庫時(shí),會將數(shù)據(jù)寫入緩存,則變?yōu)樯厦娴?ldquo;一致”狀態(tài))。

“數(shù)據(jù)不一致”:緩存的數(shù)據(jù)值≠數(shù)據(jù)庫中的值;緩存或者數(shù)據(jù)庫中存在舊值,導(dǎo)致其他線程讀到舊數(shù)據(jù)。

在這里插入圖片描述

一致性就是數(shù)據(jù)保持一致,在分布式系統(tǒng)中,可以理解為多個(gè)節(jié)點(diǎn)中數(shù)據(jù)的值是一致的。

  • 強(qiáng)一致性:這種一致性級別是最符合用戶直覺的,它要求系統(tǒng)寫入什么,讀出來的也會是什么,用戶體驗(yàn)好,但實(shí)現(xiàn)起來往往對系統(tǒng)的性能影響大
  • 弱一致性:這種一致性級別約束了系統(tǒng)在寫入成功后,不承諾立即可以讀到寫入的值,也不承諾多久之后數(shù)據(jù)能夠達(dá)到一致,但會盡可能地保證到某個(gè)時(shí)間級別(比如秒級別)后,數(shù)據(jù)能夠達(dá)到一致狀態(tài)
  • 最終一致性:最終一致性是弱一致性的一個(gè)特例,系統(tǒng)會保證在一定時(shí)間內(nèi),能夠達(dá)到一個(gè)數(shù)據(jù)一致的狀態(tài)。這里之所以將最終一致性單獨(dú)提出來,是因?yàn)樗侨跻恢滦灾蟹浅M瞥绲囊环N一致性模型,也是業(yè)界在大型分布式系統(tǒng)的數(shù)據(jù)一致性上比較推崇的模型

導(dǎo)致數(shù)據(jù)不一致的原因?

1) 在高并發(fā)的業(yè)務(wù)場景下,數(shù)據(jù)庫大多數(shù)情況都是用戶并發(fā)訪問最薄弱的環(huán)節(jié)。所以,就需要使用redis做一個(gè)緩沖操作,讓請求先訪問到redis,而不是直接訪問MySQL等數(shù)據(jù)庫;

2)讀取緩存步驟一般沒有什么問題,但是一旦涉及到數(shù)據(jù)更新,數(shù)據(jù)庫和緩存更新,就容易出現(xiàn)緩存(Redis)和數(shù)據(jù)庫(MySQL)間的數(shù)據(jù)一致性問題;

3)這個(gè)業(yè)務(wù)場景,主要是解決讀數(shù)據(jù)從Redis緩存,一般都是按照下圖的流程來進(jìn)行業(yè)務(wù)操作。

在這里插入圖片描述

應(yīng)對策略

針對緩存更新問題,提出了一個(gè)旁路緩存的緩存更新套路,這個(gè)策略分為以下三種場景:

1)失效:應(yīng)用程序先從緩存取數(shù)據(jù),沒有得到,則從數(shù)據(jù)庫中取數(shù)據(jù),成功后,放到緩存中。

2)命中:應(yīng)用程序從緩存中取數(shù)據(jù),取到后返回。

3)更新:先把數(shù)據(jù)存到數(shù)據(jù)庫中,成功后,再讓緩存失效。

不管是先刪緩存再更新數(shù)據(jù)庫還是先更新數(shù)據(jù)庫再刪緩存,都會導(dǎo)致緩存跟數(shù)據(jù)不一致問題!

先寫MySQL,再寫Redis

在這里插入圖片描述

先寫Redis,再寫MySQL

在這里插入圖片描述

先刪除Redis,再寫MySQL

在這里插入圖片描述

先寫 MySQL,再刪除 Redis

在這里插入圖片描述

不管是先寫數(shù)據(jù)庫,再刪除緩存;還是先刪除緩存,再寫庫,都有可能出現(xiàn)數(shù)據(jù)不一致的情況。

現(xiàn)有的大部分業(yè)務(wù)場景下大多采用讀寫分離的操作來提升數(shù)據(jù)庫吞吐量,但是并發(fā)讀寫訪問的時(shí)候,對緩存和數(shù)據(jù)庫相互交叉執(zhí)行操作,則會出現(xiàn)數(shù)據(jù)不一致問題。

在進(jìn)行數(shù)據(jù)更新時(shí),就涉及到先更新緩存還是先更新數(shù)據(jù)庫了,其實(shí)兩種方式都有數(shù)據(jù)一致性問題:

舉個(gè)例子:假如業(yè)務(wù)A為寫請求,業(yè)務(wù)B為讀請求

1.先更新數(shù)據(jù)庫再更新緩存

步驟1:業(yè)務(wù)A先更新數(shù)據(jù)庫,此時(shí)該業(yè)務(wù)線由于宕機(jī)或者其他原因延遲沒有繼續(xù)進(jìn)行。

步驟2:業(yè)務(wù)B讀取數(shù)據(jù),讀取的是緩存中的舊數(shù)據(jù)。

步驟3:業(yè)務(wù)A恢復(fù)過來,更新緩存

可以看到,由于寫請求延遲,可能會讀到舊的緩存數(shù)據(jù)。

2.先更新緩存再更新數(shù)據(jù)庫

步驟1:業(yè)務(wù)A先刪除緩存

步驟2:業(yè)務(wù)B進(jìn)入,業(yè)務(wù)B發(fā)現(xiàn)緩存中沒有數(shù)據(jù),直接從數(shù)據(jù)庫中進(jìn)行讀取,讀到了數(shù)據(jù)庫中的舊數(shù)據(jù)

步驟3:業(yè)務(wù)A更新數(shù)據(jù)庫并返回。

可以看到,由于寫請求延遲,可能讀到舊的數(shù)據(jù)庫數(shù)據(jù)。

因?yàn)閷懞妥x是并發(fā)的,沒法保證順序,就會出現(xiàn)緩存和數(shù)據(jù)庫的數(shù)據(jù)不一致的問題。

解決方案

(1)讀寫請求串行化

最為簡單的一種方法,寫請求在更新之前需要先獲得分布式鎖,獲取到鎖才能去更新數(shù)據(jù)庫,獲取不到則進(jìn)行等待,超時(shí)直接返回更新失敗。更新完數(shù)據(jù)庫后更新緩存,如果更新失敗,放到內(nèi)存隊(duì)列中進(jìn)行重新嘗試。讀請求則同樣需要獲得鎖,然判斷緩存中是否有數(shù)據(jù),有則直接讀緩存,沒有則直接讀數(shù)據(jù)庫,并更新緩存。

這種方案可以保證數(shù)據(jù)的一致性。但是會降低系統(tǒng)吞吐量(等待時(shí)間長),這在需要數(shù)據(jù)強(qiáng)一致的情況下適用。(銀行轉(zhuǎn)賬)

(2)刪除緩存

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

先刪除緩存,后更新數(shù)據(jù)庫,第二步操作失敗,數(shù)據(jù)庫沒有更新成功,那下次讀緩存發(fā)現(xiàn)不存在則從數(shù)據(jù)庫中讀取,并重建緩存,此時(shí)數(shù)據(jù)庫和緩存依日保持一致。

但如果是先更新數(shù)據(jù)庫,后刪除緩存,第二步操作失敗,數(shù)據(jù)庫是最新值,緩存中是舊值,發(fā)生不致。所以,這個(gè)方案依舊存在問題。

總之,和前面提到的問題類似,第二步失敗依舊有不一致的風(fēng)險(xiǎn)

我們再來看[并發(fā)]問題,這個(gè)問題是我們需要關(guān)注的[重點(diǎn)]

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

依舊是 2 個(gè)線程并發(fā)[讀寫]數(shù)據(jù)

1.緩存中 X 不存在 (數(shù)據(jù)庫 X = 1)

2.線程 A 讀取數(shù)據(jù)庫,得到目值 (X = 1)

3.線程 B 更新數(shù)據(jù)庫 (X = 2)

4.線程 B 刪除緩存

5.線程 A 將日值寫入緩存 (X = 1)

最終 X的值在緩存中是 1 (日值) ,在數(shù)據(jù)庫中是 2(新值),也發(fā)生不一致

這種情況[理論]來說是可能發(fā)生的,但實(shí)際真的有可能發(fā)生嗎?

其實(shí)概率[很低],這是因?yàn)樗仨殱M足 3 個(gè)條件

1.緩存剛好已失效

2.讀請求 + 寫請求并發(fā)

3.更新數(shù)據(jù)庫 + 除緩存的時(shí)間 (步 3-4) ,要比讀數(shù)據(jù)庫 + 寫緩存時(shí)間短(步 2 和5)

仔細(xì)想一下,條件 3 發(fā)生的概率其實(shí)是非常低的因?yàn)閷憯?shù)據(jù)庫一般會先[加鎖],所以寫數(shù)據(jù)庫,通常是要比讀數(shù)據(jù)庫的時(shí)間更長的這么來看,[先更新數(shù)據(jù)庫 + 再刪除緩存]的方案,是可以保證數(shù)據(jù)一致性的。

所以,我們應(yīng)該采用這種方案,來操作數(shù)據(jù)庫和緩存

如何保證兩步都執(zhí)行成功?

無論是更新緩存還是刪除緩存,只要第二步發(fā)生失敗,那么就會導(dǎo)致數(shù)據(jù)庫和緩存不一致。保證第二步成功執(zhí)行,就是解決問題的關(guān)鍵.

程序在執(zhí)行過程中發(fā)生異常,最簡單的解決辦法是什么?

答案是:異步重試

  • 如果是同步重試,立即重試很大概率還會失敗,[重試次數(shù)]設(shè)置多少才合理?
  • 重試會一直[占用]這個(gè)線程資源,無法服務(wù)其它客戶端請求
  • 異步其實(shí)就是把重試請求寫到消息隊(duì)列中,然后由專門的消費(fèi)者來重試,直到成功。

為了避免第二步執(zhí)行失敗,我們可以把操作緩存這一步,直接放到消息隊(duì)列中,由消費(fèi)者來操作緩存

到這里你可能會問,寫消息隊(duì)列也有可能會失敗啊? 而且,引入消息隊(duì)列,這又增加了更多的維擴(kuò)成本,這樣做值得嗎?

這個(gè)問題很好,但我們思考這樣一個(gè)問題:如果在執(zhí)行失敗的線程中一直重試,還沒等執(zhí)行成功,此時(shí)如果項(xiàng)目[重啟]了,那這次重試請求也就[丟失]了,那這條數(shù)據(jù)就一直不一致了

所以,這里我們必須把重試消息或第二步操作放到另一個(gè)[服務(wù)]中,這個(gè)服務(wù)用[消息隊(duì)列]最為合適。

  • 消息隊(duì)列保證可靠性: 寫到隊(duì)列中的消息,成功消費(fèi)之前不會丟失(重啟項(xiàng)目也不擔(dān)心)
  • 消息隊(duì)列保證消息成功投遞: 下游從隊(duì)列拉取消息,成功消費(fèi)后才會刪除消息,否則還會繼續(xù)投遞消息給消費(fèi)者 (符合我們重試的需求)

至于寫隊(duì)列失敗和消息隊(duì)列的維護(hù)成本問題

  • 寫隊(duì)列失敗: 操作緩存和寫消息隊(duì)列,[同時(shí)失敗]的概率其實(shí)是很小的維護(hù)成本:
  • 我們項(xiàng)目中一般都會用到消息隊(duì)列,維護(hù)成本并沒有新增很多

以上就是詳解MySQL和Redis如何保證數(shù)據(jù)一致性的詳細(xì)內(nèi)容,更多關(guān)于MySQL和Redis數(shù)據(jù)一致性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • mysql導(dǎo)出查詢結(jié)果到csv的實(shí)現(xiàn)方法

    mysql導(dǎo)出查詢結(jié)果到csv的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猰ysql導(dǎo)出查詢結(jié)果到csv的實(shí)現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • MySQL占用內(nèi)存較大與CPU過高測試與解決辦法

    MySQL占用內(nèi)存較大與CPU過高測試與解決辦法

    為了裝mysql環(huán)境測試,裝上后發(fā)現(xiàn)啟動后MySQL占用內(nèi)存了很大,達(dá)8百多兆。網(wǎng)上搜索了一下,得到高人指點(diǎn)my.ini。再也沒見再詳細(xì)的了..只好打開my.ini逐行的啃,雖然英文差了點(diǎn),不過多少M(fèi)還是看得明的
    2018-03-03
  • Mysql如何在select查詢時(shí)追加(添加)一個(gè)字段并指定值

    Mysql如何在select查詢時(shí)追加(添加)一個(gè)字段并指定值

    這篇文章主要介紹了Mysql如何在select查詢時(shí)追加(添加)一個(gè)字段并指定值,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • MySQL Workbench 安裝教程(保姆級)

    MySQL Workbench 安裝教程(保姆級)

    MySQL Workbench 是一款強(qiáng)大的數(shù)據(jù)庫設(shè)計(jì)和管理工具,本文主要介紹了MySQL Workbench 安裝教程,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • MySQL鎖等待排查的問題解決

    MySQL鎖等待排查的問題解決

    本文主要介紹了MySQL如何排查鎖等待問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • mysql Innodb表空間卸載、遷移、裝載的使用方法

    mysql Innodb表空間卸載、遷移、裝載的使用方法

    從MySQL的Innodb特性中我們知道,Inndob的表空間有共享和獨(dú)享的特點(diǎn),如果是共享的。則默認(rèn)會把表空間存放在一個(gè)文件中(ibdata1),當(dāng)開啟獨(dú)享表空間參數(shù)Innodb_file_per_table時(shí),會為每個(gè)Innodb表創(chuàng)建一個(gè).ibd的文件。文章討論在獨(dú)享表空間卸載、裝載、遷移Innodb表的情況
    2013-11-11
  • MySQL中?LBCC?和?MVCC?的理解及常見問題示例

    MySQL中?LBCC?和?MVCC?的理解及常見問題示例

    這篇文章主要介紹了MySQL中LBCC和MVCC的理解及常見問題示例,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的朋友可以參考一下
    2022-09-09
  • MySQL和HBase的使用對比

    MySQL和HBase的使用對比

    MySQL和HBase是兩種不同的數(shù)據(jù)庫,MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫,支持事務(wù),而HBase是一個(gè)NoSQL數(shù)據(jù)庫,支持海量數(shù)據(jù)的讀寫,MySQL適用于OLTP業(yè)務(wù),而HBase適用于OLAP業(yè)務(wù)
    2024-12-12
  • MySQL表字段設(shè)置默認(rèn)值(圖文教程及注意細(xì)節(jié))

    MySQL表字段設(shè)置默認(rèn)值(圖文教程及注意細(xì)節(jié))

    默認(rèn)值的設(shè)置很重要,比如在插入的時(shí)候一些字段是可以省略的,這會帶來很多的方便,接下來將要介紹MySQL表字段設(shè)置默認(rèn)值感興趣的你可以千萬不要走開啊,希望本文對你有所幫助
    2013-01-01
  • 手動管理MySQL8.0中的Undo表空間的使用

    手動管理MySQL8.0中的Undo表空間的使用

    本文主要介紹了MySQL 8.0中手動管理Undo表空間,包括創(chuàng)建、配置、使用和維護(hù)這些表空間的具體步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07

最新評論

青州市| 林芝县| 成安县| 山丹县| 瑞丽市| 屏边| 湟中县| 双桥区| 朝阳市| 满城县| 江陵县| SHOW| 布尔津县| 新野县| 乌拉特前旗| 泽库县| 逊克县| 兰西县| 南郑县| 麟游县| 张掖市| 明水县| 象山县| 金堂县| 清涧县| 台南市| 江源县| 柳林县| 黄浦区| 沾益县| 河津市| 电白县| 林西县| 封开县| 自治县| 莱阳市| 七台河市| 平阳县| 淮北市| 阿瓦提县| 天祝|