欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

什么是一致性

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

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

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

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

在這里插入圖片描述

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

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

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

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

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

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

在這里插入圖片描述

應(yīng)對(duì)策略

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

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

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

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

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

先寫(xiě)MySQL,再寫(xiě)Redis

在這里插入圖片描述

先寫(xiě)Redis,再寫(xiě)MySQL

在這里插入圖片描述

先刪除Redis,再寫(xiě)MySQL

在這里插入圖片描述

先寫(xiě) MySQL,再刪除 Redis

在這里插入圖片描述

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

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

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

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

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

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

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

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

可以看到,由于寫(xiě)請(qǐng)求延遲,可能會(huì)讀到舊的緩存數(shù)據(jù)。

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

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

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

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

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

因?yàn)閷?xiě)和讀是并發(fā)的,沒(méi)法保證順序,就會(huì)出現(xiàn)緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致的問(wèn)題。

解決方案

(1)讀寫(xiě)請(qǐng)求串行化

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

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

(2)刪除緩存

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

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

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

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

我們?cè)賮?lái)看[并發(fā)]問(wèn)題,這個(gè)問(wèn)題是我們需要關(guān)注的[重點(diǎn)]

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

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

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

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

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

4.線程 B 刪除緩存

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

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

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

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

1.緩存剛好已失效

2.讀請(qǐng)求 + 寫(xiě)請(qǐng)求并發(fā)

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

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

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

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

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

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

答案是:異步重試

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

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

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

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

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

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

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

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

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

相關(guān)文章

  • mysql charset=utf8你真的弄明白意思了嗎

    mysql charset=utf8你真的弄明白意思了嗎

    這篇文章主要介紹了mysql charset=utf8你真的弄明白意思了嗎?文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • MySQL在Windows上安裝的詳細(xì)流程

    MySQL在Windows上安裝的詳細(xì)流程

    MySQL 是最流行的數(shù)據(jù)庫(kù)管理系統(tǒng) (DBMS) 之一,它輕量、開(kāi)源且易于安裝和使用,因此對(duì)于那些剛開(kāi)始學(xué)習(xí)和使用關(guān)系數(shù)據(jù)庫(kù)的人來(lái)說(shuō)是一個(gè)不錯(cuò)的選擇, 本文主要系統(tǒng)介紹Windows的環(huán)境下MySQL的安裝過(guò)程和驗(yàn)證過(guò)程,需要的朋友可以參考下
    2024-12-12
  • MySQL中讀頁(yè)緩沖區(qū)buffer?pool詳解

    MySQL中讀頁(yè)緩沖區(qū)buffer?pool詳解

    這篇文章主要介紹了MySQL中讀頁(yè)緩沖區(qū)buffer?pool?,從磁盤(pán)中讀取數(shù)據(jù)到內(nèi)存的過(guò)程是十分慢的,所以我們讀取的頁(yè)面需要將其緩存起來(lái),所以MySQL有這個(gè)buffer pool對(duì)頁(yè)面進(jìn)行緩存,需要的朋友可以參考下
    2022-05-05
  • MySQL進(jìn)行表之間關(guān)聯(lián)更新的實(shí)現(xiàn)方法

    MySQL進(jìn)行表之間關(guān)聯(lián)更新的實(shí)現(xiàn)方法

    在實(shí)際編程工作或運(yùn)維實(shí)踐中,對(duì)MySQL數(shù)據(jù)庫(kù)表進(jìn)行關(guān)聯(lián)更新是一種比較常見(jiàn)的應(yīng)用場(chǎng)景,針對(duì)這樣的業(yè)務(wù)場(chǎng)景,我們來(lái)看看有什么方法可以實(shí)現(xiàn)關(guān)聯(lián)更新,需要的朋友可以參考下
    2023-10-10
  • mysql中decimal數(shù)據(jù)類型小數(shù)位填充問(wèn)題詳解

    mysql中decimal數(shù)據(jù)類型小數(shù)位填充問(wèn)題詳解

    這篇文章主要介紹了mysql中decimal數(shù)據(jù)類型小數(shù)位填充問(wèn)題詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Linux安裝MySQL的教程

    Linux安裝MySQL的教程

    這篇文章主要介紹了Linux安裝MySQL的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • MySQL可直接使用的查詢表的列信息(實(shí)現(xiàn)方案)

    MySQL可直接使用的查詢表的列信息(實(shí)現(xiàn)方案)

    本文介紹了如何使用SQL快速將下劃線命名的表字段轉(zhuǎn)換為駝峰命名格式,包括確定下劃線位置、找到第一個(gè)字符、截取并拼接字符串等步驟,通過(guò)使用LOCATE、CONCAT、UCASE和LOWER等函數(shù),可以實(shí)現(xiàn)高效的字段命名轉(zhuǎn)換,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 詳解MySQL 8.0 之不可見(jiàn)索引

    詳解MySQL 8.0 之不可見(jiàn)索引

    這篇文章主要介紹了MySQL 8.0 之不可見(jiàn)索引的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)新版本的MySQL,感興趣的朋友可以了解下
    2020-10-10
  • mysql之跨庫(kù)關(guān)聯(lián)查詢(dblink)問(wèn)題

    mysql之跨庫(kù)關(guān)聯(lián)查詢(dblink)問(wèn)題

    這篇文章主要介紹了mysql之跨庫(kù)關(guān)聯(lián)查詢(dblink)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • MySQL查看鎖表的實(shí)現(xiàn)步驟

    MySQL查看鎖表的實(shí)現(xiàn)步驟

    在MySQL數(shù)據(jù)庫(kù)中,當(dāng)多個(gè)事務(wù)同時(shí)請(qǐng)求對(duì)同一行數(shù)據(jù)進(jìn)行修改時(shí),就會(huì)發(fā)生鎖表現(xiàn)象,本文主要介紹了MySQL查看鎖表的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評(píng)論