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

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

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

說在前面

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

  


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

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

這樣就會造成數據庫中的數據與緩存中數據不一致。

那么該如何解決呢?

有下面4種解決方案:

1、 先更新緩存,再更新數據庫;
2、 先更新數據庫,再更新緩存;
3、 先刪除緩存,后更新數據庫;
4、 先更新數據庫,后刪除緩存;

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

一、先更新緩存,再更新數據庫

這個方案我們一般不考慮。原因是更新緩存成功,但是更新數據庫出現異常了。

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

  


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

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

  


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

這個方案再并發場景下也會出問題,具體出現的原因如下:

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

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

  

 這時候就會產生數據庫和Redis數據不一致的問題。

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

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

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

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

這樣做,可以將1s內所造成的緩存臟數據,再次刪除。

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

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

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

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

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

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

  

此時該如何解決呢?

解決辦法有兩個:

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

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

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

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

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

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

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

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

  

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

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

其實是依然存在的,尤其是在大型互聯網電商,高并發系統中,并發問題導致的數據一致性的數據量非常大。

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

當高并發場景下,會有如下情形出現:

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

  

 高并發場景下,確實有可能會發生上述的情況,產生臟數據。

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

?

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

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

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

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

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

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

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

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

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

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

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

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

  

方案補充(重要)

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

此時解決方案有兩個:

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

具體的業務邏輯如下:

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

  

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

所以還有一個優化的方案

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

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

業務代碼流程如下:

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

  


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

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

總結

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

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

2025-02-10 03:00:00

2023-05-26 07:34:50

RedisMySQL緩存

2021-12-14 07:15:57

MySQLRedis數據

2022-10-19 12:22:53

并發扣款一致性

2020-08-05 08:46:10

NFS網絡文件系統

2025-03-27 08:20:54

2021-06-04 09:56:12

RedisMySQL美團

2024-08-06 09:42:23

2024-08-20 16:13:52

2019-08-30 12:46:10

并發扣款查詢SQL

2023-09-07 08:11:24

Redis管道機制

2022-08-23 07:46:45

數據一致性數據庫

2024-12-26 15:01:29

2024-01-10 08:01:55

高并發場景悲觀鎖

2021-03-04 06:49:53

RocketMQ事務

2024-07-04 12:36:50

2023-09-24 14:35:43

Redis數據庫

2022-03-29 10:39:10

緩存數據庫數據

2024-10-28 12:41:25

2024-10-16 09:53:07

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 夜夜爽99久久国产综合精品女不卡 | 亚洲九色 | 一区二区av| 久久精品视频网站 | av一级久久 | 亚洲二区视频 | 久久一区二区三区四区五区 | 国产精品成人一区二区三区 | 日韩欧美三级电影在线观看 | 国产精品免费观看 | 成人久久久久久久久 | 天天草天天干天天 | 久久999| 一区二区视屏 | 欧美中文字幕在线观看 | 欧美日韩国产中文 | 日本韩国欧美在线观看 | 狠狠操操| 免费h在线 | 国产999精品久久久久久 | 91久久夜色 | 日韩美女爱爱 | 精品一区二区三区中文字幕 | 91欧美| 不卡一区二区三区四区 | 亚洲精品一区二区 | 日韩精品人成在线播放 | 亚洲国产成人av好男人在线观看 | 国产精品99久久久久久www | 激情毛片 | 欧美亚洲视频 | 一区二区视频在线 | 91大神在线资源观看无广告 | 黄视频免费观看 | 韩国电影久久 | 国产精品v | 久久久久久久久久久久久久av | 国产精品久久久久久av公交车 | 国产色在线 | 干出白浆视频 | 日韩成人精品一区二区三区 |