成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

億級流量,如何保證Redis與MySQL的一致性?失敗如何設(shè)計補償?

數(shù)據(jù)庫 MySQL
億級電商流量,高并發(fā)下Redis與MySQL的數(shù)據(jù)一致性如何保證的方案,非常圓滿了。以上的內(nèi)容,如果大家能爛熟于心、對答如流、如數(shù)家珍,基本上 面試官會被你 震驚到、吸引到。

說在前面

只要使用到緩存,無論是本地緩存還是使用Redis做緩存,那么就會存在數(shù)據(jù)同步不一致的問題。

  


1、 先讀取緩存,緩存數(shù)據(jù)有,則立即返回結(jié)果;
2、 如果緩存中沒有數(shù)據(jù),則從數(shù)據(jù)庫中讀取數(shù)據(jù);
3、 把讀取到的數(shù)據(jù)同步到緩存中,提供下次讀請求返回數(shù)據(jù);

這樣的作法是大多數(shù)人使用緩存的方式,這樣能有效減輕數(shù)據(jù)庫壓力,但是如果修改刪除數(shù)據(jù),因為緩存無法感知到數(shù)據(jù)在數(shù)據(jù)庫中的修改。

這樣就會造成數(shù)據(jù)庫中的數(shù)據(jù)與緩存中數(shù)據(jù)不一致。

那么該如何解決呢?

有下面4種解決方案:

1、 先更新緩存,再更新數(shù)據(jù)庫;
2、 先更新數(shù)據(jù)庫,再更新緩存;
3、 先刪除緩存,后更新數(shù)據(jù)庫;
4、 先更新數(shù)據(jù)庫,后刪除緩存;

下面我們一一來看下每個方案的可行性:

一、先更新緩存,再更新數(shù)據(jù)庫

這個方案我們一般不考慮。原因是更新緩存成功,但是更新數(shù)據(jù)庫出現(xiàn)異常了。

會導致緩存數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)完全不一致,而且很難察覺,因為緩存中的數(shù)據(jù)一直都存在。

  


二、先更新DB,再更新緩存

這個方案我們一般也是不考慮,原因跟方案1一樣,數(shù)據(jù)庫更新成功了,緩存更新失敗,同樣會出現(xiàn)數(shù)據(jù)不一致問題,且不容易被發(fā)現(xiàn),因為緩存中一直存在數(shù)據(jù)。

  


三、先刪除緩存,后更新DB

這個方案再并發(fā)場景下也會出問題,具體出現(xiàn)的原因如下:

兩個并發(fā)請求:請求A(更新操作)和請求B(讀取操作)

1、 請求A會先刪除Redis中的數(shù)據(jù),然后去更新數(shù)據(jù)庫;
2、 此時請求B看到Redis中的數(shù)據(jù)是空的,回去數(shù)據(jù)庫中查詢該值,補充到Redis緩存中;
3、 此時請求A并沒有更新成功,或者是事務(wù)還未提交(MySQL的事務(wù)隔離級別,會導致未提交的事務(wù)數(shù)據(jù)不會被另一個線程看到),請求B去數(shù)據(jù)庫查詢得到舊值.;

  

 這時候就會產(chǎn)生數(shù)據(jù)庫和Redis數(shù)據(jù)不一致的問題。

因此一般也不建議這種方式

雖然不建議,但是如果你是采用了這種方式,該如何解決數(shù)據(jù)不一致的問題呢?

其實最簡單的辦法就是延時雙刪的策略:

1、 先淘汰緩存;
2、 再寫數(shù)據(jù)庫;
3、 休眠1s,再次淘汰緩存;

這樣做,可以將1s內(nèi)所造成的緩存臟數(shù)據(jù),再次刪除。

但是,但是,這個1s怎么確定的,具體該休眠多久呢?

1、 自行評估自己的項目的讀數(shù)據(jù)業(yè)務(wù)邏輯的耗時(這個我們可以利用SkyWalking等監(jiān)控工具評估耗時);
2、 評估寫數(shù)據(jù)的休眠時間(在讀數(shù)據(jù)業(yè)務(wù)耗時的基礎(chǔ)上,加幾百ms即可);

這樣做的目的,就是確保讀請求結(jié)束,寫請求可以刪除讀請求造成的緩存臟數(shù)據(jù)。

延時雙刪就能徹底解決不一致嗎?如果面試官這樣問你,你千萬不能回答是的。

第一,我們評估的延時時間(讀請求耗時+幾百毫秒),并不能完全代表實際運行過程中的耗時,運行過程如果因為系統(tǒng)壓力過大,我們評估的耗時就是不準確,仍然會導致數(shù)據(jù)不一致的出現(xiàn)

第二,延時雙刪雖然在保證事務(wù)提交完以后再進行刪除緩存,但是如果你使用的是MySQL的讀寫分離的機構(gòu),主從同步之間其實也會有時間差。

  

此時該如何解決呢?

解決辦法有兩個:

1、 還是使用延時雙刪策略,只是睡眠時間改為在主從同步的延時時間基礎(chǔ)上,加幾百毫秒(讀接口耗時+主從延遲時間+幾百毫秒);
2、 對Redis進行填充數(shù)據(jù)查詢(更新緩存時查詢數(shù)據(jù)庫),強制走主庫查詢,那么我們延時雙刪就沒必要增加主從延時時間了(增加個主從延時時間也會增加更大的不確定性,因為主從延時時間也是不穩(wěn)定的);

如果面試官繼續(xù)深入的問你,采用這種同步延時雙刪的淘汰策略,接口的吞吐量降低怎么辦?(數(shù)據(jù)變更時,更新接口都要多休眠一個延時時間)

既然同步會降低吞吐量,那就同步改異步(性能優(yōu)化的常用手段)。

將第二次刪除的操作,異步起一個線程,異步刪除,這樣寫的請求就不用沉睡一段時間后才能返回了。

總的來說,先刪除緩存,再更新數(shù)據(jù)庫的方式,還是瑕疵較多,發(fā)生數(shù)據(jù)一致性的問題和性能問題的概率更大。比如:

1、 先刪除緩存可能導致讀請求因緩存缺失而大量訪問數(shù)據(jù)庫(尤其是高并發(fā)場景的電商,可能一瞬間就把數(shù)據(jù)庫打掛了);
2、 讀請求接口的耗時和寫緩存的時間,估算不夠準確,會導致延遲雙刪中的sleep時間不好設(shè)置;

下面我們來看最后一種解決方案,這個解決方式是4個方案中發(fā)生數(shù)據(jù)不一致性的概率最低的。

四、先更新DB,后刪除緩存

  

 讀的時候,先讀緩存,緩存沒有的話,就讀數(shù)據(jù)庫,然后取出數(shù)據(jù)后放入緩
存,同時返回響應。更新的時候,先更新數(shù)據(jù)庫,然后再刪除緩存。

這種方案下就不存在數(shù)據(jù)不一致性的問題了么?

其實是依然存在的,尤其是在大型互聯(lián)網(wǎng)電商,高并發(fā)系統(tǒng)中,并發(fā)問題導致的數(shù)據(jù)一致性的數(shù)據(jù)量非常大。

假設(shè)兩個請求,請求A和請求B,請求A做查詢操作(讀請求),請求B做更新操作(寫請求)

當高并發(fā)場景下,會有如下情形出現(xiàn):

1、 緩存剛好失效;
2、 請求A查詢數(shù)據(jù)庫,得到一個舊值;
3、 請求B將新值寫入數(shù)據(jù)庫;
4、 請求B刪除緩存;
5、 請求A將查到的舊值寫入緩存;

  

 高并發(fā)場景下,確實有可能會發(fā)生上述的情況,產(chǎn)生臟數(shù)據(jù)。

然而,發(fā)生這種的概率又有多少呢?

?

發(fā)生上述情況的一個先天性條件,就是步驟(3)的寫數(shù)據(jù)庫操作比步驟(2)的讀數(shù)據(jù)庫操作耗時更短,才有可能使得步驟(4)先于步驟(5)。

可是,大家想想,數(shù)據(jù)庫的讀操作的速度遠快于寫操作的(不然做讀寫分離干嘛,做讀寫分離的意義就是因為讀操作比較快,耗資源少)。

因此步驟(3)耗時比步驟(2) 更短,這一情形很難出現(xiàn)。

但是,如果面試官問你:如果我的業(yè)務(wù)屬性要求一定要解決怎么辦?那么如何解決上述并發(fā)問題?

首先,給緩存設(shè)置過期時間是一種有效的方案。

如果你的業(yè)務(wù)數(shù)據(jù)對實時性要求不是很高,可以接受數(shù)據(jù)的短時間數(shù)據(jù)不一致的場景,我們此種方案就可以解決了(比如商品詳情中的描述、屬性等)

其次,仍可以采用異步延時刪除的策略。

參考方案3中的異步延時刪除策略方案,刪除的方案其實還有問題,這個我們放在后面說

一般采用這些手段幾乎就已經(jīng)把Redis緩存和數(shù)據(jù)庫數(shù)據(jù)不一致的概率降到了極低。

如果非要強一致性,極低的數(shù)據(jù)不一致的概率都不能接受,那么該如何解決呢?

其實也有解決方案:那就是加鎖,在讀請求加一個讀鎖,所有的讀請求不阻塞,在寫請求加一個寫鎖,一旦有寫請求,則暫時阻塞讀,等寫請求處理完,刪除完緩存再放開讀。

如果你的業(yè)務(wù)并發(fā)要求不高,讀多寫少,且對數(shù)據(jù)一致性有很高的要求,可以采用這種方案,但是保證強一致性的同時,就會損失一些性能,所以該不該用這種方案,大家可以根據(jù)自己業(yè)務(wù)的屬性做好權(quán)衡。

  

方案補充(重要)

3、 4都屬于刪除緩存類,其實刪除緩存類都會有一個共同的問題,那就是在刪除緩存的階段出錯了怎么辦?此時再讀取緩存的時候每次都是錯誤的數(shù)據(jù)了;

此時解決方案有兩個:

一、利用消息隊列進行刪除失敗的補償

具體的業(yè)務(wù)邏輯如下:

1、 請求A先對數(shù)據(jù)庫進行更新操作;
2、 在對Redis進行刪除操作的時候發(fā)現(xiàn)報錯,刪除失敗;
3、 此時將Redis的key作為消息體發(fā)送到消息隊列中;
4、 系統(tǒng)接收到消息隊列發(fā)送的消息后;
5、 再次對Redis進行刪除操作;

  

但是這個方案會有一個缺點,就是會對業(yè)務(wù)代碼造成大量的侵入,深深的耦合在一起。

所以還有一個優(yōu)化的方案

二、訂閱MySQL的binlog日志,異步刪除

我們知道對 Mysql 數(shù)據(jù)庫更新操作后 ,在 binlog日志中我們都能夠找到相應的操作,那么我們可以訂閱 Mysql數(shù)據(jù)庫 的 binlog日志對緩存進行操作,這樣就達到了一個解耦的目的了。

業(yè)務(wù)代碼流程如下:

1、 更新數(shù)據(jù)庫,更新完成后,觸發(fā)binlog消息;
2、 經(jīng)常B(消費者)訂閱binlog消息,執(zhí)行緩存刪除操作;
3、 緩存刪除失敗,將刪除任務(wù)丟到消息隊列中;
4、 進程B獲取刪除失敗任務(wù);
5、 執(zhí)行二次刪除redis緩存;

  


說到底就是通過數(shù)據(jù)庫的 binlog 來異步淘汰 key,利用工具(canal)將 binlog
日志采集發(fā)送到 MQ 中,然后通過 ACK 機制確認處理刪除緩存。
先更新DB,后刪除緩存,這種方式,被稱為 Cache Aside Pattern,屬于緩存更新的經(jīng)典設(shè)計模式之一。

所以如果大家做緩存與數(shù)據(jù)庫的同步,推薦大家選擇這一種方式。

總結(jié)

至此,億級電商流量,高并發(fā)下Redis與MySQL的數(shù)據(jù)一致性如何保證的方案,非常圓滿了。以上的內(nèi)容,如果大家能爛熟于心、對答如流、如數(shù)家珍,基本上 面試官會被你 震驚到、吸引到。

責任編輯:武曉燕 來源: 程序員江小北
相關(guān)推薦

2025-02-10 03:00:00

2023-05-26 07:34:50

RedisMySQL緩存

2021-12-14 07:15:57

MySQLRedis數(shù)據(jù)

2022-10-19 12:22:53

并發(fā)扣款一致性

2020-08-05 08:46:10

NFS網(wǎng)絡(luò)文件系統(tǒng)

2025-03-27 08:20:54

2021-06-04 09:56:12

RedisMySQL美團

2024-08-06 09:42:23

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2024-08-20 16:13:52

2023-09-07 08:11:24

Redis管道機制

2022-08-23 07:46:45

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

2024-12-26 15:01:29

2024-01-10 08:01:55

高并發(fā)場景悲觀鎖

2021-03-04 06:49:53

RocketMQ事務(wù)

2024-07-04 12:36:50

2023-09-24 14:35:43

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

2022-03-29 10:39:10

緩存數(shù)據(jù)庫數(shù)據(jù)

2024-10-28 12:41:25

2024-01-15 10:38:20

多級緩存數(shù)據(jù)一致性分布式緩存
點贊
收藏

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

主站蜘蛛池模板: 日韩视频一区在线观看 | 99精品国产一区二区三区 | 日韩字幕 | www.欧美.com | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 午夜av在线 | 一区二区三区久久久 | 欧美一区二区三区四区视频 | 欧美激情精品久久久久久 | 永久免费视频 | 久久久久国产精品 | 久久av一区二区 | 日本三级做a全过程在线观看 | 久久国产精品视频 | 成人国产在线观看 | 欧美性久久久 | 欧美一级大片免费观看 | 狠狠操av| 黄色一级网 | 久久合久久| 国产福利视频在线观看 | 青青草中文字幕 | 精品免费av | 国产一区二区三区 | 91高清免费 | 国产传媒视频在线观看 | 成人婷婷 | 中文字幕第十五页 | 精品欧美一区二区三区久久久 | 国产美女精品视频免费观看 | 日韩久久综合 | 色综合久久久久 | 国产亚洲日本精品 | 日韩在线一区二区 | 91国产精品在线 | 一级黄色在线 | 精品国产一区二区三区久久 | 久久精品欧美一区二区三区不卡 | 成人福利网站 | 亚洲精品一区二区三区在线 | 成年人在线观看 |