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

趣說(shuō) | 數(shù)據(jù)庫(kù)和緩存如何保證一致性?

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
「先更新數(shù)據(jù)庫(kù),再刪緩存」的策略的第一步是更新數(shù)據(jù)庫(kù),那么更新數(shù)據(jù)庫(kù)成功,就會(huì)產(chǎn)生一條變更日志,記錄在 binlog 里。

一天,老板說(shuō)「最近公司的用戶越來(lái)越多了,但是服務(wù)器的訪問(wèn)速度越來(lái)越差的,阿旺幫我優(yōu)化下,做好了給你畫個(gè)餅!」。

程序員阿旺聽(tīng)到老板口中的「畫餅」后就非常期待,沒(méi)有任何猶豫就接下了老板給的這個(gè)任務(wù)。

阿旺登陸到了服務(wù)器,經(jīng)過(guò)一番排查后,確認(rèn)服務(wù)器的性能瓶頸是在數(shù)據(jù)庫(kù)。

這好辦,給服務(wù)器加上 Redis,讓其作為數(shù)據(jù)庫(kù)的緩存。

這樣,在客戶端請(qǐng)求數(shù)據(jù)時(shí),如果能在緩存中命中數(shù)據(jù),那就查詢緩存,不用在去查詢數(shù)據(jù)庫(kù),從而減輕數(shù)據(jù)庫(kù)的壓力,提高服務(wù)器的性能。

先更新數(shù)據(jù)庫(kù),還是先更新緩存?

阿旺有了這個(gè)想法后,就準(zhǔn)備開(kāi)始著手優(yōu)化服務(wù)器,但是擋在在他前面的是這樣的一個(gè)問(wèn)題。

由于引入了緩存,那么在數(shù)據(jù)更新時(shí),不僅要更新數(shù)據(jù)庫(kù),而且要更新緩存,這兩個(gè)更新操作存在前后的問(wèn)題:

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

阿旺沒(méi)想到太多,他覺(jué)得最新的數(shù)據(jù)肯定要先更新數(shù)據(jù)庫(kù),這樣才可以確保數(shù)據(jù)庫(kù)里的數(shù)據(jù)是最新的,于是他就采用了「先更新數(shù)據(jù)庫(kù),再更新緩存」的方案。

阿旺經(jīng)過(guò)幾個(gè)夜晚的折騰,終于「優(yōu)化好了服務(wù)器」,然后就直接上線了,自信心滿滿跑去跟老板匯報(bào)。

老板不懂技術(shù),自然也沒(méi)多慮,就讓后續(xù)阿旺觀察下服務(wù)器的情況,如果效果不錯(cuò),就跟阿旺談畫餅的事情。

阿旺觀察了好幾天,發(fā)現(xiàn)數(shù)據(jù)庫(kù)的壓力大大減少了,訪問(wèn)速度也提高了不少,心想這事肯定成的了。

好景不長(zhǎng),突然老板收到一個(gè)客戶的投訴,客戶說(shuō)他剛發(fā)起了兩次更新年齡的操作,但是顯示的年齡確還是第一次更新時(shí)的年齡,而第二次更新年齡并沒(méi)有生效。

老板立馬就找了阿旺,訓(xùn)斥著阿旺說(shuō):「這么簡(jiǎn)單的更新操作,都有 bug?我臉往哪兒放?你的餅還要不要了?」

聽(tīng)到自己準(zhǔn)備到手的餅要沒(méi)了的阿旺瞬間就慌了,立馬登陸服務(wù)器排查問(wèn)題,阿旺查詢緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)后發(fā)現(xiàn)了問(wèn)題。

數(shù)據(jù)庫(kù)的數(shù)據(jù)是客戶第二次更新操作的數(shù)據(jù),而緩存確還是第一次更新操作的數(shù)據(jù),也就是出現(xiàn)了數(shù)據(jù)庫(kù)和緩存的數(shù)據(jù)不一致的問(wèn)題。

這個(gè)問(wèn)題可大了,阿旺經(jīng)過(guò)一輪的分析,造成緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致的現(xiàn)象,是因?yàn)椴l(fā)問(wèn)題!

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

舉個(gè)例子,比如「請(qǐng)求 A 」和「請(qǐng)求 B 」兩個(gè)請(qǐng)求,同時(shí)更新「同一條」數(shù)據(jù),則可能出現(xiàn)這樣的順序:

A 請(qǐng)求先將數(shù)據(jù)庫(kù)的數(shù)據(jù)更新為 1,然后在更新緩存前,請(qǐng)求 B 將數(shù)據(jù)庫(kù)的數(shù)據(jù)更新為 2,緊接著也把緩存更新為 2,然后 A 請(qǐng)求更新緩存為 1。

此時(shí),數(shù)據(jù)庫(kù)中的數(shù)據(jù)是 2,而緩存中的數(shù)據(jù)卻是 1,出現(xiàn)了緩存和數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致的現(xiàn)象。

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

那換成「先更新緩存,再更新數(shù)據(jù)庫(kù)」這個(gè)方案,還會(huì)有問(wèn)題嗎?

依然還是存在并發(fā)的問(wèn)題,分析思路也是一樣。

假設(shè)「請(qǐng)求 A 」和「請(qǐng)求 B 」兩個(gè)請(qǐng)求,同時(shí)更新「同一條」數(shù)據(jù),則可能出現(xiàn)這樣的順序:

A 請(qǐng)求先將緩存的數(shù)據(jù)更新為 1,然后在更新數(shù)據(jù)庫(kù)前,B 請(qǐng)求來(lái)了, 將緩存的數(shù)據(jù)更新為 2,緊接著把數(shù)據(jù)庫(kù)更新為 2,然后 A 請(qǐng)求將數(shù)據(jù)庫(kù)的數(shù)據(jù)更新為 1。

此時(shí),數(shù)據(jù)庫(kù)中的數(shù)據(jù)是 1,而緩存中的數(shù)據(jù)卻是 2,出現(xiàn)了緩存和數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致的現(xiàn)象。

所以,無(wú)論是「先更新數(shù)據(jù)庫(kù),再更新緩存」,還是「先更新緩存,再更新數(shù)據(jù)庫(kù)」,這兩個(gè)方案都存在并發(fā)問(wèn)題,當(dāng)兩個(gè)請(qǐng)求并發(fā)更新同一條數(shù)據(jù)的時(shí)候,可能會(huì)出現(xiàn)緩存和數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致的現(xiàn)象。

先更新數(shù)據(jù)庫(kù),還是先刪除緩存?

阿旺定位出問(wèn)題后,思考了一番后,決定在更新數(shù)據(jù)時(shí),不更新緩存,而是刪除緩存中的數(shù)據(jù)。然后,到讀取數(shù)據(jù)時(shí),發(fā)現(xiàn)緩存中沒(méi)了數(shù)據(jù)之后,再?gòu)臄?shù)據(jù)庫(kù)中讀取數(shù)據(jù),更新到緩存中。

阿旺想的這個(gè)策略是有名字的,是叫 Cache Aside 策略,中文是叫旁路緩存策略。

該策略又可以細(xì)分為「讀策略」和「寫策略」。

寫策略的步驟:

  • 更新數(shù)據(jù)庫(kù)中的數(shù)據(jù);
  • 刪除緩存中的數(shù)據(jù)。

讀策略的步驟:

  • 如果讀取的數(shù)據(jù)命中了緩存,則直接返回?cái)?shù)據(jù);
  • 如果讀取的數(shù)據(jù)沒(méi)有命中緩存,則從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),然后將數(shù)據(jù)寫入到緩存,并且返回給用戶。

阿旺在想到「寫策略」的時(shí)候,又陷入更深層次的思考,到底該選擇哪種順序呢?

  • 先刪除緩存,再更新數(shù)據(jù)庫(kù);
  • 先更新數(shù)據(jù)庫(kù),再刪除緩存。

阿旺這次經(jīng)過(guò)上次教訓(xùn),不再「想當(dāng)然」的亂選方案,因?yàn)槔习暹@次給的餅很大啊,必須把握住。

于是阿旺用并發(fā)的角度來(lái)分析,看看這兩種方案哪個(gè)可以保證數(shù)據(jù)庫(kù)與緩存的數(shù)據(jù)一致性。

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

阿旺還是以用戶表的場(chǎng)景來(lái)分析。

假設(shè)某個(gè)用戶的年齡是 20,請(qǐng)求 A 要更新用戶年齡為 21,所以它會(huì)刪除緩存中的內(nèi)容。這時(shí),另一個(gè)請(qǐng)求 B 要讀取這個(gè)用戶的年齡,它查詢緩存發(fā)現(xiàn)未命中后,會(huì)從數(shù)據(jù)庫(kù)中讀取到年齡為 20,并且寫入到緩存中,然后請(qǐng)求 A 繼續(xù)更改數(shù)據(jù)庫(kù),將用戶的年齡更新為 21。

最終,該用戶年齡在緩存中是 20(舊值),在數(shù)據(jù)庫(kù)中是 21(新值),緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致。

可以看到,先刪除緩存,再更新數(shù)據(jù)庫(kù),在「讀 + 寫」并發(fā)的時(shí)候,還是會(huì)出現(xiàn)緩存和數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致的問(wèn)題。

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

繼續(xù)用「讀 + 寫」請(qǐng)求的并發(fā)的場(chǎng)景來(lái)分析。

假如某個(gè)用戶數(shù)據(jù)在緩存中不存在,請(qǐng)求 A 讀取數(shù)據(jù)時(shí)從數(shù)據(jù)庫(kù)中查詢到年齡為 20,在未寫入緩存中時(shí)另一個(gè)請(qǐng)求 B 更新數(shù)據(jù)。它更新數(shù)據(jù)庫(kù)中的年齡為 21,并且清空緩存。這時(shí)請(qǐng)求 A 把從數(shù)據(jù)庫(kù)中讀到的年齡為 20 的數(shù)據(jù)寫入到緩存中。

最終,該用戶年齡在緩存中是 20(舊值),在數(shù)據(jù)庫(kù)中是 21(新值),緩存和數(shù)據(jù)庫(kù)數(shù)據(jù)不一致。

從上面的理論上分析,先更新數(shù)據(jù)庫(kù),再刪除緩存也是會(huì)出現(xiàn)數(shù)據(jù)不一致性的問(wèn)題,但是在實(shí)際中,這個(gè)問(wèn)題出現(xiàn)的概率并不高。

因?yàn)榫彺娴膶懭胪ǔRh(yuǎn)遠(yuǎn)快于數(shù)據(jù)庫(kù)的寫入,所以在實(shí)際中很難出現(xiàn)請(qǐng)求 B 已經(jīng)更新了數(shù)據(jù)庫(kù)并且刪除了緩存,請(qǐng)求 A 才更新完緩存的情況。

而一旦請(qǐng)求 A 早于請(qǐng)求 B 刪除緩存之前更新了緩存,那么接下來(lái)的請(qǐng)求就會(huì)因?yàn)榫彺娌幻卸鴱臄?shù)據(jù)庫(kù)中重新讀取數(shù)據(jù),所以不會(huì)出現(xiàn)這種不一致的情況。

所以,「先更新數(shù)據(jù)庫(kù) + 再刪除緩存」的方案,是可以保證數(shù)據(jù)一致性的。

而且阿旺為了確保萬(wàn)無(wú)一失,還給緩存數(shù)據(jù)加上了「過(guò)期時(shí)間」,就算在這期間存在緩存數(shù)據(jù)不一致,有過(guò)期時(shí)間來(lái)兜底,這樣也能達(dá)到最終一致。

阿旺思考到這一步后,覺(jué)得自己真的是個(gè)小天才,因?yàn)樗谷幌氲搅藗€(gè)「天衣無(wú)縫」的方案,他二話不說(shuō)就采用了這個(gè)方案,又經(jīng)過(guò)幾天的折騰,終于完成了。

他自信滿滿的向老板匯報(bào),已經(jīng)解決了上次客戶的投訴的問(wèn)題了。老板覺(jué)得阿旺這小伙子不錯(cuò),這么快就解決問(wèn)題了,然后讓阿旺在觀察幾天。

事情哪有這么順利呢?結(jié)果又沒(méi)過(guò)多久,老板又收到客戶的投訴了,說(shuō)自己明明更新了數(shù)據(jù),但是數(shù)據(jù)要過(guò)一段時(shí)間才生效,客戶接受不了。

老板面無(wú)表情的找上阿旺,讓阿旺盡快查出問(wèn)題。

阿旺得知又有 Bug 就更慌了,立馬就登錄服務(wù)器去排查問(wèn)題,查看日志后得知了原因。

「先更新數(shù)據(jù)庫(kù), 再刪除緩存」其實(shí)是兩個(gè)操作,前面的所有分析都是建立在這兩個(gè)操作都能同時(shí)執(zhí)行成功,而這次客戶投訴的問(wèn)題就在于,在****刪除緩存(第二個(gè)操作)的時(shí)候失敗了,導(dǎo)致緩存中的數(shù)據(jù)是舊值。

好在之前給緩存加上了過(guò)期時(shí)間,所以才會(huì)出現(xiàn)客戶說(shuō)的過(guò)一段時(shí)間才更新生效的現(xiàn)象,假設(shè)如果沒(méi)有這個(gè)過(guò)期時(shí)間的兜底,那后續(xù)的請(qǐng)求讀到的就會(huì)一直是緩存中的舊數(shù)據(jù),這樣問(wèn)題就更大了。

所以新的問(wèn)題來(lái)了,如何保證「先更新數(shù)據(jù)庫(kù) ,再刪除緩存」這兩個(gè)操作能執(zhí)行成功?

阿旺分析出問(wèn)題后,慌慌張張的向老板匯報(bào)了問(wèn)題。

老板知道事情后,又給了阿旺幾天來(lái)解決這個(gè)問(wèn)題,畫餅的事情這次沒(méi)有再提了。

阿旺會(huì)用什么方式來(lái)解決這個(gè)問(wèn)題呢?

老板畫的餅事情,能否兌現(xiàn)給阿旺呢?

預(yù)知后事,且聽(tīng)下回阿旺的故事。

小結(jié)

阿旺的事情就聊到這,我們繼續(xù)說(shuō)點(diǎn)其他。

「先更新數(shù)據(jù)庫(kù),再刪除緩存」的方案雖然保證了數(shù)據(jù)庫(kù)與緩存的數(shù)據(jù)一致性,但是每次更新數(shù)據(jù)的時(shí)候,緩存的數(shù)據(jù)都會(huì)被刪除,這樣會(huì)對(duì)緩存的命中率帶來(lái)影響。

所以,如果我們的業(yè)務(wù)對(duì)緩存命中率有很高的要求,我們可以采用「更新數(shù)據(jù)庫(kù) + 更新緩存」的方案,因?yàn)楦戮彺娌⒉粫?huì)出現(xiàn)緩存未命中的情況。

但是這個(gè)方案前面我們也分析過(guò),在兩個(gè)更新請(qǐng)求并發(fā)執(zhí)行的時(shí)候,會(huì)出現(xiàn)數(shù)據(jù)不一致的問(wèn)題,因?yàn)楦聰?shù)據(jù)庫(kù)和更新緩存這兩個(gè)操作是獨(dú)立的,而我們又沒(méi)有對(duì)操作做任何并發(fā)控制,那么當(dāng)兩個(gè)線程并發(fā)更新它們的話,就會(huì)因?yàn)閷懭腠樞虻牟煌斐蓴?shù)據(jù)的不一致。

所以我們得增加一些手段來(lái)解決這個(gè)問(wèn)題,這里提供兩種做法:

  • 在更新緩存前先加個(gè)分布式鎖,保證同一時(shí)間只運(yùn)行一個(gè)請(qǐng)求更新緩存,就會(huì)不會(huì)產(chǎn)生并發(fā)問(wèn)題了,當(dāng)然引入了鎖后,對(duì)于寫入的性能就會(huì)帶來(lái)影響。
  • 在更新完緩存時(shí),給緩存加上較短的過(guò)期時(shí)間,這樣即時(shí)出現(xiàn)緩存不一致的情況,緩存的數(shù)據(jù)也會(huì)很快過(guò)期,對(duì)業(yè)務(wù)還是能接受的。

對(duì)了,針對(duì)「先刪除緩存,再刪除數(shù)據(jù)庫(kù)」方案在「讀 + 寫」并發(fā)請(qǐng)求而造成緩存不一致的解決辦法是「延遲雙刪」。

延遲雙刪實(shí)現(xiàn)的偽代碼如下:

#刪除緩存
redis.delKey(X)
#更新數(shù)據(jù)庫(kù)
db.update(X)
#睡眠
Thread.sleep(N)
#再刪除緩存
redis.delKey(X)

加了個(gè)睡眠時(shí)間,主要是為了確保請(qǐng)求 A 在睡眠的時(shí)候,請(qǐng)求 B 能夠在這這一段時(shí)間完成「從數(shù)據(jù)庫(kù)讀取數(shù)據(jù),再把缺失的緩存寫入緩存」的操作,然后請(qǐng)求 A 睡眠完,再刪除緩存。

所以,請(qǐng)求 A 的睡眠時(shí)間就需要大于請(qǐng)求 B 「從數(shù)據(jù)庫(kù)讀取數(shù)據(jù) + 寫入緩存」的時(shí)間。

但是具體睡眠多久其實(shí)是個(gè)玄學(xué),很難評(píng)估出來(lái),所以這個(gè)方案也只是盡可能保證一致性而已,極端情況下,依然也會(huì)出現(xiàn)緩存不一致的現(xiàn)象。

因此,還是比較建議用「先更新數(shù)據(jù)庫(kù),再刪除緩存」的方案。

前情回顧

上回程序員阿旺為了提升數(shù)據(jù)訪問(wèn)的性能,引入 Redis 作為 MySQL 緩存層,但是這件事情并不是那么簡(jiǎn)單,因?yàn)檫€要考慮 Redis 和 MySQL 雙寫一致性的問(wèn)題。

阿旺經(jīng)過(guò)一番周折,最終選用了「先更新數(shù)據(jù)庫(kù),再刪緩存」的策略,原因是這個(gè)策略即使在并發(fā)讀寫時(shí),也能最大程度保證數(shù)據(jù)一致性。

聰明的阿旺還搞了個(gè)兜底的方案,就是給緩存加上了過(guò)期時(shí)間。

本以為就這樣不會(huì)在出現(xiàn)數(shù)據(jù)一致性的問(wèn)題,結(jié)果將功能上線后,老板還是收到用戶的投訴「說(shuō)自己明明更新了數(shù)據(jù),但是數(shù)據(jù)要過(guò)一段時(shí)間才生效」,客戶接受不了。

老板轉(zhuǎn)告給了阿旺,阿旺得知又有 Bug 就更慌了,立馬就登錄服務(wù)器去排查問(wèn)題,查看日志后得知了原因。

「先更新數(shù)據(jù)庫(kù), 再刪除緩存」其實(shí)是兩個(gè)操作,這次客戶投訴的問(wèn)題就在于,在刪除緩存(第二個(gè)操作)的時(shí)候失敗了,導(dǎo)致緩存中的數(shù)據(jù)是舊值,而數(shù)據(jù)庫(kù)是最新值。

好在之前給緩存加上了過(guò)期時(shí)間,所以才會(huì)出現(xiàn)客戶說(shuō)的過(guò)一段時(shí)間才更新生效的現(xiàn)象,假設(shè)如果沒(méi)有這個(gè)過(guò)期時(shí)間的兜底,那后續(xù)的請(qǐng)求讀到的就會(huì)一直是緩存中的舊數(shù)據(jù),這樣問(wèn)題就更大了。

所以新的問(wèn)題來(lái)了,如何保證「先更新數(shù)據(jù)庫(kù) ,再刪除緩存」這兩個(gè)操作能執(zhí)行成功?

阿旺分析出問(wèn)題后,慌慌張張的向老板匯報(bào)了問(wèn)題。

老板知道事情后,又給了阿旺幾天來(lái)解決這個(gè)問(wèn)題,畫餅的事情這次沒(méi)有再提了。

  • 阿旺會(huì)用什么方式來(lái)解決這個(gè)問(wèn)題呢?
  • 老板畫的餅事情,能否兌現(xiàn)給阿旺呢?

如何保證兩個(gè)操作都能執(zhí)行成功?

這次用戶的投訴是因?yàn)樵趧h除緩存(第二個(gè)操作)的時(shí)候失敗了,導(dǎo)致緩存還是舊值,而數(shù)據(jù)庫(kù)是最新值,造成數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)不一致的問(wèn)題,會(huì)對(duì)敏感業(yè)務(wù)造成影響。

舉個(gè)例子,來(lái)說(shuō)明下。

應(yīng)用要把數(shù)據(jù) X 的值從 1 更新為 2,先成功更新了數(shù)據(jù)庫(kù),然后在 Redis 緩存中刪除 X 的緩存,但是這個(gè)操作卻失敗了,這個(gè)時(shí)候數(shù)據(jù)庫(kù)中 X 的新值為 2,Redis 中的 X 的緩存值為 1,出現(xiàn)了數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)不一致的問(wèn)題。

那么,后續(xù)有訪問(wèn)數(shù)據(jù) X 的請(qǐng)求,會(huì)先在 Redis 中查詢,因?yàn)榫彺娌](méi)有 誒刪除,所以會(huì)緩存命中,但是讀到的卻是舊值 1。

其實(shí)不管是先操作數(shù)據(jù)庫(kù),還是先操作緩存,只要第二個(gè)操作失敗都會(huì)出現(xiàn)數(shù)據(jù)一致的問(wèn)題。

問(wèn)題原因知道了,該怎么解決呢?有兩種方法:

  • 重試機(jī)制。
  • 訂閱 MySQL binlog,再操作緩存。

先來(lái)說(shuō)第一種。

重試機(jī)制

我們可以引入消息隊(duì)列,將第二個(gè)操作(刪除緩存)要操作的數(shù)據(jù)加入到消息隊(duì)列,由消費(fèi)者來(lái)操作數(shù)據(jù)。

  • 如果應(yīng)用刪除緩存失敗,可以從消息隊(duì)列中重新讀取數(shù)據(jù),然后再次刪除緩存,這個(gè)就是重試機(jī)制。當(dāng)然,如果重試超過(guò)的一定次數(shù),還是沒(méi)有成功,我們就需要向業(yè)務(wù)層發(fā)送報(bào)錯(cuò)信息了。
  • 如果刪除緩存成功,就要把數(shù)據(jù)從消息隊(duì)列中移除,避免重復(fù)操作,否則就繼續(xù)重試。

舉個(gè)例子,來(lái)說(shuō)明重試機(jī)制的過(guò)程。

訂閱 MySQL binlog,再操作緩存

「先更新數(shù)據(jù)庫(kù),再刪緩存」的策略的第一步是更新數(shù)據(jù)庫(kù),那么更新數(shù)據(jù)庫(kù)成功,就會(huì)產(chǎn)生一條變更日志,記錄在 binlog 里。

于是我們就可以通過(guò)訂閱 binlog 日志,拿到具體要操作的數(shù)據(jù),然后再執(zhí)行緩存刪除,阿里巴巴開(kāi)源的 Canal 中間件就是基于這個(gè)實(shí)現(xiàn)的。

Canal 模擬 MySQL 主從復(fù)制的交互協(xié)議,把自己偽裝成一個(gè) MySQL 的從節(jié)點(diǎn),向 MySQL 主節(jié)點(diǎn)發(fā)送 dump 請(qǐng)求,MySQL 收到請(qǐng)求后,就會(huì)開(kāi)始推送 Binlog 給 Canal,Canal 解析 Binlog 字節(jié)流之后,轉(zhuǎn)換為便于讀取的結(jié)構(gòu)化數(shù)據(jù),供下游程序訂閱使用。

下圖是 Canal 的工作原理:

所以,如果要想保證「先更新數(shù)據(jù)庫(kù),再刪緩存」策略第二個(gè)操作能執(zhí)行成功,我們可以使用「消息隊(duì)列來(lái)重試緩存的刪除」,或者「訂閱 MySQL binlog 再操作緩存」,這兩種方法有一個(gè)共同的特點(diǎn),都是采用異步操作緩存。

老板發(fā)餅啦

阿旺由于對(duì)消息隊(duì)列比較熟悉,所以他決定采用「消息隊(duì)列來(lái)重試緩存的刪除」的方案,來(lái)解決這次的用戶問(wèn)題。

經(jīng)過(guò)幾天幾夜的操作,服務(wù)器搞定啦,立馬向老板匯報(bào)工作。

老板讓阿旺再觀察些時(shí)間,如果沒(méi)問(wèn)題,到中秋節(jié)就商量“餅”的事情。

時(shí)間過(guò)的很快,中秋佳節(jié)到了,這期間一直都沒(méi)有用戶反饋數(shù)據(jù)不一致的問(wèn)題。

老板見(jiàn)這次阿旺表現(xiàn)很好,沒(méi)有再出現(xiàn)任何差錯(cuò),服務(wù)器的訪問(wèn)性能也上來(lái)了,于是給阿旺發(fā)了這個(gè)超級(jí)大的月餅,你看這個(gè)餅又大又圓,就像你的代碼又長(zhǎng)又多。

責(zé)任編輯:武曉燕 來(lái)源: 小林coding
相關(guān)推薦

2022-03-31 08:21:14

數(shù)據(jù)庫(kù)緩存雙寫數(shù)據(jù)一致性

2024-10-28 12:41:25

2022-03-29 10:39:10

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

2024-12-26 15:01:29

2020-09-03 09:45:38

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

2020-06-01 22:09:48

緩存緩存同步緩存誤用

2022-02-23 09:17:09

數(shù)據(jù)庫(kù)分離變更

2025-04-27 08:52:21

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

2021-12-01 08:26:27

數(shù)據(jù)庫(kù)緩存技術(shù)

2021-06-11 09:21:58

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

2018-05-16 16:10:28

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

2022-10-19 12:22:53

并發(fā)扣款一致性

2022-12-05 08:24:32

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

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2025-03-27 08:20:54

2023-09-07 08:11:24

Redis管道機(jī)制

2024-01-15 10:38:20

多級(jí)緩存數(shù)據(jù)一致性分布式緩存

2022-12-14 08:23:30

2021-03-04 06:49:53

RocketMQ事務(wù)

2024-08-20 16:13:52

點(diǎn)贊
收藏

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