新聞中心
如何解決Redis緩存和MySQL數(shù)據(jù)一致性的問(wèn)題?
Redis緩存和MySQL數(shù)據(jù)一致性的問(wèn)題,相信大家在大量使用redis緩存進(jìn)行業(yè)務(wù)開(kāi)發(fā)的場(chǎng)景下是一定要考慮的問(wèn)題。

總有運(yùn)營(yíng)、產(chǎn)品、測(cè)試人員過(guò)來(lái)問(wèn)你為什么我剛剛更新了一條數(shù)據(jù),APP上還是原來(lái)的數(shù)據(jù)呢?你總是一句話:“加了緩存,等會(huì)兒就好”。有可能是1分鐘,有可能是半小時(shí)。問(wèn)你的都屬于關(guān)系不錯(cuò),不問(wèn)你直接給你提bug你也沒(méi)辦法。
下面就分享一下我個(gè)人在工作中對(duì)如何解決redis緩存和MySQL數(shù)據(jù)一致性的一些心得:
大家看了這個(gè)圖是不是就知道什么意思了?一個(gè)請(qǐng)求過(guò)來(lái)查詢數(shù)據(jù),我先看看redis有沒(méi)有,有直接返回,沒(méi)有就去數(shù)據(jù)庫(kù)查出來(lái),順便同步到redis,設(shè)置一下過(guò)期時(shí)間。下次同樣的數(shù)據(jù)查詢r(jià)edis緩存就可以直接返回了。是不是很簡(jiǎn)單很粗暴?在實(shí)時(shí)性要求不高的場(chǎng)景下,這種方式我估計(jì)是大家最常用的一種方式。但是他有幾個(gè)問(wèn)題:
無(wú)法保證一致性:數(shù)據(jù)庫(kù)更改了數(shù)據(jù),redis里的數(shù)據(jù)就和數(shù)據(jù)庫(kù)不一致了,產(chǎn)生臟讀;
緩存雪崩:這種方案要求redis里的緩存必須設(shè)置有效期,如果在同一時(shí)間大面積過(guò)期,所有請(qǐng)求壓力都指向數(shù)據(jù)庫(kù),這個(gè)時(shí)候數(shù)據(jù)庫(kù)頂不住壓力就會(huì)宕機(jī),然后整個(gè)世界都安靜了;
緩存穿透:查詢一個(gè)數(shù)據(jù),緩存沒(méi)有,去查詢數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)也沒(méi)有,怎么辦?這樣的請(qǐng)求多了對(duì)數(shù)據(jù)庫(kù)也是壓力,沒(méi)有數(shù)據(jù)的時(shí)候也需要在redis緩存一個(gè)空值。
針對(duì)第一種方案的問(wèn)題,那么大多數(shù)時(shí)候我們會(huì)繼續(xù)做一個(gè)job,去定時(shí)同步數(shù)據(jù)庫(kù)里的數(shù)據(jù)都redis緩存中,我們的業(yè)務(wù)請(qǐng)求直接查詢r(jià)edis緩存,無(wú)論有或者沒(méi)有數(shù)據(jù)都直接返回結(jié)果。這樣可以避免緩存穿透、緩存雪崩等問(wèn)題,也能緩解redis緩存和數(shù)據(jù)庫(kù)不一致的情況,但是還無(wú)法徹底解決一致性的問(wèn)題。在job的間隔期內(nèi)對(duì)數(shù)據(jù)的修改必須要等到下一次job的運(yùn)行。
對(duì)軟件開(kāi)發(fā)同學(xué)來(lái)說(shuō),這個(gè)場(chǎng)景太常見(jiàn)了?;镜乃悸肥牵簃ysql數(shù)據(jù)發(fā)生變更的時(shí)候,要及時(shí)清除redis緩存。那究竟要怎樣清除呢?
分兩種情況來(lái)說(shuō)吧。
單集群。在redis集群和mysql集群都是單集群部署的情況下,需要確保如果redis查不到數(shù)據(jù)讀取mysql主庫(kù)來(lái)填充數(shù)據(jù),此時(shí)只需要在mysql變更生效后,直接調(diào)用redis清緩存即可。
多集群。在redis集群和mysql集群都是多地多機(jī)房的部署情況下。采用單集群清緩存策略清除本機(jī)房redis集群緩存后,延遲消息通知其他機(jī)房redis集群(確保其他機(jī)房mysql集群已收到本機(jī)房mysql集群的binlog變更消息并將變更生效)。
希望能解答您的問(wèn)題,喜歡的話可以關(guān)注下我哈
要看應(yīng)用場(chǎng)景,數(shù)據(jù)變動(dòng)頻繁的環(huán)境中,使用讀緩存是毫無(wú)意義的,反而加重系統(tǒng)負(fù)荷,因?yàn)橐ㄙM(fèi)額外資源維護(hù)緩存和數(shù)據(jù)源的一致性。
其實(shí)redis可以當(dāng)作數(shù)據(jù)庫(kù)的元數(shù)據(jù)使用,設(shè)計(jì)好數(shù)據(jù)結(jié)構(gòu)就是一個(gè)簡(jiǎn)單的關(guān)系型庫(kù),業(yè)務(wù)數(shù)據(jù)完全放到redis中運(yùn)行,MySQL當(dāng)作后備庫(kù)使用。redis也有持久化機(jī)制而且很容易做鏡像,因此可以在很大時(shí)間粒度上進(jìn)行數(shù)據(jù)同步,比如一天同步一次。而業(yè)務(wù)層只操作redis,與數(shù)據(jù)庫(kù)完全剝離,即使數(shù)據(jù)庫(kù)掛掉也不會(huì)導(dǎo)致業(yè)務(wù)中斷。
隨著技術(shù)發(fā)展,現(xiàn)在項(xiàng)目技術(shù)選型不像從前那樣單一的,特別是在高并發(fā)場(chǎng)景下的項(xiàng)目,都是多種技術(shù)配套著來(lái)使用。在以前,對(duì)于用戶數(shù)據(jù)無(wú)論是增刪改查,我們都是直接操作數(shù)據(jù)庫(kù)的,但在高并發(fā)場(chǎng)景下這樣做顯然是不合理的,于是乎我們?cè)贒B層之前加上Cache層,以此來(lái)緩解DB層的壓力。
在業(yè)界通常是將MySQL作為數(shù)據(jù)最終落地的存儲(chǔ)方案,而用Redis來(lái)緩存熱點(diǎn)數(shù)據(jù)。一般是讀數(shù)據(jù)是從Redis中讀取,增刪改則是操作MySQL。但是這樣會(huì)存在一個(gè)問(wèn)題,即:讀操作和寫(xiě)操作是并發(fā)的,執(zhí)行順序無(wú)法保證,這樣很容易出現(xiàn)緩存數(shù)據(jù)與數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致。
舉例說(shuō)明一下:
假設(shè)我們更新了數(shù)據(jù)庫(kù)后,緩存一直沒(méi)有失效,那我們從緩存中讀取的就是臟數(shù)據(jù)。
假設(shè)緩存中的數(shù)據(jù)不存在,我們從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)然后存入緩存,此時(shí)數(shù)據(jù)庫(kù)剛好更新,那在緩存期間內(nèi),這個(gè)緩存數(shù)據(jù)就是臟數(shù)據(jù)。
如何避免Redis和MySQL中數(shù)據(jù)一致性問(wèn)題呢?結(jié)合我的經(jīng)驗(yàn)給出一些方案供大家參考:
1、首先確定你的業(yè)務(wù)是否要求緩存和數(shù)據(jù)庫(kù)之間是強(qiáng)一致性關(guān)系
如果你的業(yè)務(wù)要求數(shù)據(jù)庫(kù)和緩存之間是強(qiáng)一致性,那你要做的就是確保每次更新了MySQL后就同步更新Redis;
如果不需要強(qiáng)一致性,那我們合理控制好緩存的TTL即可。
2、借助MQ消息來(lái)更新緩存
到此,以上就是小編對(duì)于redis事務(wù)能保證一致性嗎為什么的問(wèn)題就介紹到這了,希望這1點(diǎn)解答對(duì)大家有用。
網(wǎng)頁(yè)名稱:redis事務(wù)能保證一致性嗎
URL標(biāo)題:http://m.fisionsoft.com.cn/article/cdsiieh.html


咨詢
建站咨詢
