偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

說(shuō)在前面

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

  


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

這樣的作法是大多數(shù)人使用緩存的方式,這樣能有效減輕數(shù)據(jù)庫(kù)壓力,但是如果修改刪除數(shù)據(jù),因?yàn)榫彺鏌o(wú)法感知到數(shù)據(jù)在數(shù)據(jù)庫(kù)中的修改。

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

那么該如何解決呢?

有下面4種解決方案:

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

下面我們一一來(lái)看下每個(gè)方案的可行性:

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

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

會(huì)導(dǎo)致緩存數(shù)據(jù)與數(shù)據(jù)庫(kù)數(shù)據(jù)完全不一致,而且很難察覺(jué),因?yàn)榫彺嬷械臄?shù)據(jù)一直都存在。

  


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

這個(gè)方案我們一般也是不考慮,原因跟方案1一樣,數(shù)據(jù)庫(kù)更新成功了,緩存更新失敗,同樣會(huì)出現(xiàn)數(shù)據(jù)不一致問(wèn)題,且不容易被發(fā)現(xiàn),因?yàn)榫彺嬷幸恢贝嬖跀?shù)據(jù)。

  


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

這個(gè)方案再并發(fā)場(chǎng)景下也會(huì)出問(wèn)題,具體出現(xiàn)的原因如下:

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

1、 請(qǐng)求A會(huì)先刪除Redis中的數(shù)據(jù),然后去更新數(shù)據(jù)庫(kù);
2、 此時(shí)請(qǐng)求B看到Redis中的數(shù)據(jù)是空的,回去數(shù)據(jù)庫(kù)中查詢(xún)?cè)撝担a(bǔ)充到Redis緩存中;
3、 此時(shí)請(qǐng)求A并沒(méi)有更新成功,或者是事務(wù)還未提交(MySQL的事務(wù)隔離級(jí)別,會(huì)導(dǎo)致未提交的事務(wù)數(shù)據(jù)不會(huì)被另一個(gè)線(xiàn)程看到),請(qǐng)求B去數(shù)據(jù)庫(kù)查詢(xún)得到舊值.;

  

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

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

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

其實(shí)最簡(jiǎn)單的辦法就是延時(shí)雙刪的策略:

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

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

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

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

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

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

第一,我們?cè)u(píng)估的延時(shí)時(shí)間(讀請(qǐng)求耗時(shí)+幾百毫秒),并不能完全代表實(shí)際運(yùn)行過(guò)程中的耗時(shí),運(yùn)行過(guò)程如果因?yàn)橄到y(tǒng)壓力過(guò)大,我們?cè)u(píng)估的耗時(shí)就是不準(zhǔn)確,仍然會(huì)導(dǎo)致數(shù)據(jù)不一致的出現(xiàn)

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

  

此時(shí)該如何解決呢?

解決辦法有兩個(gè):

1、 還是使用延時(shí)雙刪策略,只是睡眠時(shí)間改為在主從同步的延時(shí)時(shí)間基礎(chǔ)上,加幾百毫秒(讀接口耗時(shí)+主從延遲時(shí)間+幾百毫秒);
2、 對(duì)Redis進(jìn)行填充數(shù)據(jù)查詢(xún)(更新緩存時(shí)查詢(xún)數(shù)據(jù)庫(kù)),強(qiáng)制走主庫(kù)查詢(xún),那么我們延時(shí)雙刪就沒(méi)必要增加主從延時(shí)時(shí)間了(增加個(gè)主從延時(shí)時(shí)間也會(huì)增加更大的不確定性,因?yàn)橹鲝难訒r(shí)時(shí)間也是不穩(wěn)定的);

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

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

將第二次刪除的操作,異步起一個(gè)線(xiàn)程,異步刪除,這樣寫(xiě)的請(qǐng)求就不用沉睡一段時(shí)間后才能返回了。

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

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

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

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

  

 讀的時(shí)候,先讀緩存,緩存沒(méi)有的話(huà),就讀數(shù)據(jù)庫(kù),然后取出數(shù)據(jù)后放入緩
存,同時(shí)返回響應(yīng)。更新的時(shí)候,先更新數(shù)據(jù)庫(kù),然后再刪除緩存。

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

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

假設(shè)兩個(gè)請(qǐng)求,請(qǐng)求A和請(qǐng)求B,請(qǐng)求A做查詢(xún)操作(讀請(qǐng)求),請(qǐng)求B做更新操作(寫(xiě)請(qǐng)求)

當(dāng)高并發(fā)場(chǎng)景下,會(huì)有如下情形出現(xiàn):

1、 緩存剛好失效;
2、 請(qǐng)求A查詢(xún)數(shù)據(jù)庫(kù),得到一個(gè)舊值;
3、 請(qǐng)求B將新值寫(xiě)入數(shù)據(jù)庫(kù);
4、 請(qǐng)求B刪除緩存;
5、 請(qǐng)求A將查到的舊值寫(xiě)入緩存;

  

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

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

?

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

可是,大家想想,數(shù)據(jù)庫(kù)的讀操作的速度遠(yuǎn)快于寫(xiě)操作的(不然做讀寫(xiě)分離干嘛,做讀寫(xiě)分離的意義就是因?yàn)樽x操作比較快,耗資源少)。

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

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

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

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

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

參考方案3中的異步延時(shí)刪除策略方案,刪除的方案其實(shí)還有問(wèn)題,這個(gè)我們放在后面說(shuō)

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

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

其實(shí)也有解決方案:那就是加鎖,在讀請(qǐng)求加一個(gè)讀鎖,所有的讀請(qǐng)求不阻塞,在寫(xiě)請(qǐng)求加一個(gè)寫(xiě)鎖,一旦有寫(xiě)請(qǐng)求,則暫時(shí)阻塞讀,等寫(xiě)請(qǐng)求處理完,刪除完緩存再放開(kāi)讀。

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

  

方案補(bǔ)充(重要)

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

此時(shí)解決方案有兩個(gè):

一、利用消息隊(duì)列進(jìn)行刪除失敗的補(bǔ)償

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

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ā)送的消息后;
5、 再次對(duì)Redis進(jìn)行刪除操作;

  

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

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

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

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

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

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

  


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

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

總結(jié)

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

責(zé)任編輯:武曉燕 來(lái)源: 程序員江小北
相關(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ā)扣款一致性

2024-08-06 09:42:23

2021-06-04 09:56:12

RedisMySQL美團(tuán)

2019-08-30 12:46:10

并發(fā)扣款查詢(xún)SQL

2025-03-27 08:20:54

2020-08-05 08:46:10

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

2024-08-20 16:13:52

2022-08-23 07:46:45

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

2024-01-10 08:01:55

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

2024-12-26 15:01:29

2023-09-07 08:11:24

Redis管道機(jī)制

2021-03-04 06:49:53

RocketMQ事務(wù)

2024-07-04 12:36:50

2023-09-24 14:35:43

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

2020-06-01 22:09:48

緩存緩存同步緩存誤用

2020-09-03 09:45:38

緩存數(shù)據(jù)庫(kù)分布式

2022-02-17 21:04:27

數(shù)據(jù)庫(kù)MysqlRedis
點(diǎn)贊
收藏

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