自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何保障 MySQL 和 Redis 的數(shù)據(jù)一致性?

數(shù)據(jù)庫
在滿足實時性的條件下,MySQL 和 Redis 不存在兩者完全保存一致的方案,只有最終一致性方案。

?大家好,我是樓仔!

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

之前也看了很多相關(guān)的文章,但是感覺講的都不好,很多文章都會去講各種策略,比如(旁路緩存)策略、(讀穿 / 寫穿)策略和(寫回)策略等,感覺意義真的不大,然后有的文章也只講了部分情況,也沒有告訴最優(yōu)解。

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

圖片

不好的方案

1. 先寫 MySQL,再寫 Redis

圖片

圖解說明:

  • 這是一副時序圖,描述請求的先后調(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

圖片

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

3. 先刪除 Redis,再寫 MySQL

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

圖片

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

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

好的方案

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

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

圖片

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

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

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

圖片

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

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

簡單小結(jié)一下:

  • “緩存雙刪”不要用無腦的 sleep 500 ms;
  • 通過消息隊列的異步&串行,實現(xiàn)最后一次緩存刪除;
  • 緩存刪除失敗,增加重試機(jī)制。

5. 先寫 MySQL,再刪除 Redis

圖片

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

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

圖片

這里需要滿足 2 個條件:

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

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

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

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

圖片

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

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

幾種方案比較

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

(1) 先寫 Redis,再寫 MySQL

  • 這種方案,我肯定不會用,萬一 DB 掛了,你把數(shù)據(jù)寫到緩存,DB 無數(shù)據(jù),這個是災(zāi)難性的;
  • 我之前也見同學(xué)這么用過,如果寫 DB 失敗,對 Redis 進(jìn)行逆操作,那如果逆操作失敗呢,是不是還要搞個重試?

(2) 先寫 MySQL,再寫 Redis

  • 對于并發(fā)量、一致性要求不高的項目,很多就是這么用的,我之前也經(jīng)常這么搞,但是不建議這么做;
  • 當(dāng) Redis 瞬間不可用的情況,需要報警出來,然后線下處理。

(3) 先刪除 Redis,再寫 MySQL

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

(4) 先刪除 Redis,再寫 MySQL,再刪除 Redis

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

(5) 先寫 MySQL,再刪除 Redis

  • 比較推薦這種方式,刪除 Redis 如果失敗,可以再多重試幾次,否則報警出來;
  • 這個方案,是實時性中最好的方案,在一些高并發(fā)場景中,推薦這種。

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

  • 對于異地容災(zāi)、數(shù)據(jù)匯總等,建議會用這種方式,比如 binlog + kafka,數(shù)據(jù)的一致性也可以達(dá)到秒級;
  • 純粹的高并發(fā)場景,不建議用這種方案,比如搶購、秒殺等。

個人結(jié)論

  • 實時一致性方案:采用“先寫 MySQL,再刪除 Redis”的策略,這種情況雖然也會存在兩者不一致,但是需要滿足的條件有點(diǎn)苛刻,所以是滿足實時性條件下,能盡量滿足一致性的最優(yōu)解。
  • 最終一致性方案:采用“先寫 MySQL,通過 Binlog,異步更新 Redis”,可以通過 Binlog,結(jié)合消息隊列異步更新 Redis,是最終一致性的最優(yōu)解。???
責(zé)任編輯:趙寧寧 來源: 樓仔
相關(guān)推薦

2022-02-17 21:04:27

數(shù)據(jù)庫MysqlRedis

2023-05-26 07:34:50

RedisMySQL緩存

2021-12-14 07:15:57

MySQLRedis數(shù)據(jù)

2023-12-01 13:51:21

數(shù)據(jù)一致性數(shù)據(jù)庫

2023-09-24 14:35:43

Redis數(shù)據(jù)庫

2025-03-27 08:20:54

2024-08-20 16:13:52

2023-06-29 08:00:59

redis數(shù)據(jù)MySQL

2024-12-26 15:01:29

2023-09-07 08:11:24

Redis管道機(jī)制

2024-05-30 07:00:51

2021-10-14 10:00:46

MYSQL開發(fā)數(shù)據(jù)

2021-12-05 21:06:27

軟件

2021-10-13 09:55:11

流計算引擎數(shù)據(jù)

2021-10-18 10:30:59

流計算阿里云

2023-12-28 13:47:24

Redis高可用

2024-01-22 08:52:00

AQS雙異步數(shù)據(jù)一致性

2022-09-26 08:01:02

數(shù)據(jù)節(jié)點(diǎn)系統(tǒng)

2024-07-04 12:36:50

2025-04-27 08:52:21

Redis數(shù)據(jù)庫緩存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號