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

一文講透數(shù)據(jù)庫與 Redis 緩存一致性問題

數(shù)據(jù)庫 其他數(shù)據(jù)庫
所謂緩存,實際上就是用空間換時間,準(zhǔn)確地說是用更高速的空間來換時間,從而整體上提升讀的性能。

在真實的業(yè)務(wù)場景中,我們的業(yè)務(wù)的數(shù)據(jù)——例如訂單、會員、支付等——都是持久化到數(shù)據(jù)庫中的,因為數(shù)據(jù)庫能有很好的事務(wù)保證、持久化保證。

但是,正因為數(shù)據(jù)庫要能夠滿足這么多優(yōu)秀的功能特性,使得數(shù)據(jù)庫在設(shè)計上通常難以兼顧到性能,因此往往不能滿足大型流量下的性能要求,像是 MySQL 數(shù)據(jù)庫只能承擔(dān)“千”這個級別的 QPS,否則很可能會不穩(wěn)定,進(jìn)而導(dǎo)致整個系統(tǒng)的故障。

但是客觀上,我們的業(yè)務(wù)規(guī)模很可能要求著更高的 QPS,有些業(yè)務(wù)的規(guī)模本身就非常大,也有些業(yè)務(wù)會遇到一些流量高峰,比如電商會遇到大促的情況。

而這時候大部分的流量實際上都是讀請求,而且大部分?jǐn)?shù)據(jù)也是沒有那么多變化的,如熱門商品信息、微博的內(nèi)容等常見數(shù)據(jù)就是如此。此時,緩存就是我們應(yīng)對此類場景的利器。

1.緩存的意義

所謂緩存,實際上就是用空間換時間,準(zhǔn)確地說是用更高速的空間來換時間,從而整體上提升讀的性能。

何為更高速的空間呢?

更快的存儲介質(zhì)。通常情況下,如果說數(shù)據(jù)庫的速度慢,就得用更快的存儲組件去替代它,目前最常見的就是 Redis(內(nèi)存存儲)。Redis 單實例的讀 QPS 可以高達(dá) 10w/s,90% 的場景下只需要正確使用 Redis 就能應(yīng)對。

就近使用本地內(nèi)存。就像 CPU 也有高速緩存一樣,緩存也可以分為一級緩存、二級緩存。即便 Redis 本身性能已經(jīng)足夠高了,但訪問一次 Redis 畢竟也需要一次網(wǎng)絡(luò) IO,而使用本地內(nèi)存無疑有更快的速度。不過單機(jī)的內(nèi)存是十分有限的,所以這種一級緩存只能存儲非常少量的數(shù)據(jù),通常是最熱點的那些 key 對應(yīng)的數(shù)據(jù)。這就相當(dāng)于額外消耗寶貴的服務(wù)內(nèi)存去換取高速的讀取性能。

2.引入緩存后的一致性挑戰(zhàn)

用空間換時間,意味著數(shù)據(jù)同時存在于多個空間。最常見的場景就是數(shù)據(jù)同時存在于 Redis 與 MySQL 上(為了問題的普適性,后面舉例中若沒有特別說明,緩存均指 Redis 緩存)。

實際上,最權(quán)威最全的數(shù)據(jù)還是在 MySQL 里的。而萬一 Redis 數(shù)據(jù)沒有得到及時的更新(例如數(shù)據(jù)庫更新了沒更新到 Redis),就出現(xiàn)了數(shù)據(jù)不一致。

大部分情況下,只要使用了緩存,就必然會有不一致的情況出現(xiàn),只是說這個不一致的時間窗口是否能做到足夠的小。有些不合理的設(shè)計可能會導(dǎo)致數(shù)據(jù)持續(xù)不一致,這是我們需要改善設(shè)計去避免的。

這里的一致性實際上對于本地緩存也是同理的,例如數(shù)據(jù)庫更新后沒有及時更新本地緩存,也是有一致性問題的,下文統(tǒng)一以 Redis 緩存作為引子講述,實際上處理本地緩存原理基本一致。

緩存不一致性無法客觀地完全消滅

為什么我們幾乎沒辦法做到緩存和數(shù)據(jù)庫之間的強一致呢?

理想情況下,我們需要在數(shù)據(jù)庫更新完后把對應(yīng)的最新數(shù)據(jù)同步到緩存中,以便在讀請求的時候能讀到新的數(shù)據(jù)而不是舊的數(shù)據(jù)(臟數(shù)據(jù))。但是很可惜,由于數(shù)據(jù)庫和 Redis 之間是沒有事務(wù)保證的,所以我們無法確保寫入數(shù)據(jù)庫成功后,寫入 Redis 也是一定成功的;即便 Redis 寫入能成功,在數(shù)據(jù)庫寫入成功后到 Redis 寫入成功前的這段時間里,Redis 數(shù)據(jù)也肯定是和 MySQL 不一致的。如下兩圖所示:

圖片圖片

無法事務(wù)保持一致

所以說這個時間窗口是沒辦法完全消滅的,除非我們付出極大的代價,使用分布式事務(wù)等各種手段去維持強一致,但是這樣會使得系統(tǒng)的整體性能大幅度下降,甚至比不用緩存還慢,這樣不就與我們使用緩存的目標(biāo)背道而馳了嗎?

不過雖然無法做到強一致,但是我們能做到的是緩存與數(shù)據(jù)庫達(dá)到最終一致,而且不一致的時間窗口我們能做到盡可能短,按照經(jīng)驗來說,如果能將時間優(yōu)化到 1ms 之內(nèi),這個一致性問題帶來的影響我們就可以忽略不計。

圖片圖片

3.更新緩存的手段

通常情況下,我們在處理查詢請求的時候,使用緩存的邏輯如下:

data = queryDataRedis(key);
if (data ==null) {
     data = queryDataMySQL(key); //緩存查詢不到,從MySQL做查詢
     if (data!=null) {
         updateRedis(key, data);//查詢完數(shù)據(jù)后更新MySQL最新數(shù)據(jù)到Redis
     }
}

也就是說優(yōu)先查詢緩存,查詢不到才查詢數(shù)據(jù)庫。如果這時候數(shù)據(jù)庫查到數(shù)據(jù)了,就將緩存的數(shù)據(jù)進(jìn)行更新。這是我們常說的 cache aside 的策略,也是最常用的策略。

這樣的邏輯是正確的,而一致性的問題一般不來源于此,而是出現(xiàn)在處理寫請求的時候。所以我們簡化成最簡單的寫請求的邏輯,此時你可能會面臨多個選擇,究竟是直接更新緩存,還是失效緩存?而無論是更新緩存還是失效緩存,都可以選擇在更新數(shù)據(jù)庫之前,還是之后操作。

這樣就演變出 4 個策略:更新數(shù)據(jù)庫后更新緩存、更新數(shù)據(jù)庫前更新緩存、更新數(shù)據(jù)庫后刪除緩存、更新數(shù)據(jù)庫前刪除緩存。下面我們來分別講述。

更新數(shù)據(jù)庫后更新緩存的不一致問題

一種常見的操作是,設(shè)置一個過期時間,讓寫請求以數(shù)據(jù)庫為準(zhǔn),過期后,讀請求同步數(shù)據(jù)庫中的最新數(shù)據(jù)給緩存。那么在加入了過期時間后,是否就不會有問題了呢?并不是這樣。

大家設(shè)想一下這樣的場景。

假如這里有一個計數(shù)器,把數(shù)據(jù)庫自減 1,原始數(shù)據(jù)庫數(shù)據(jù)是 100,同時有兩個寫請求申請計數(shù)減一,假設(shè)線程 A 先減數(shù)據(jù)庫成功,線程 B 后減數(shù)據(jù)庫成功。那么這時候數(shù)據(jù)庫的值是 98,緩存里正確的值應(yīng)該也要是 98。

但是特殊場景下,你可能會遇到這樣的情況:

  • 線程 A 和線程 B 同時更新這個數(shù)據(jù)。
  • 更新數(shù)據(jù)庫的順序是先 A 后 B。
  • 更新緩存時順序是先 B 后 A。

如果我們的代碼邏輯還是更新數(shù)據(jù)庫后立刻更新緩存的數(shù)據(jù),那么——

updateMySQL();
updateRedis(key, data);

就可能出現(xiàn):數(shù)據(jù)庫的值是 100->99->98,但是緩存的數(shù)據(jù)卻是 100->98->99,也就是數(shù)據(jù)庫與緩存的不一致。而且這個不一致只能等到下一次數(shù)據(jù)庫更新或者緩存失效才可能修復(fù)。

時間

線程A(寫請求)

線程B(寫請求)

問題

T1

更新數(shù)據(jù)庫為99



T2


更新數(shù)據(jù)庫為98


T3


更新緩存數(shù)據(jù)為98


T4

更新緩存數(shù)據(jù)為99


此時緩存的值被顯式更新為99,但是實際上數(shù)據(jù)庫的值已經(jīng)是98,數(shù)據(jù)不一致

當(dāng)然,如果更新 Redis 本身是失敗的話,兩邊的值固然也是不一致的,這個前文也闡述過,幾乎無法根除。

圖片圖片

更新數(shù)據(jù)庫前更新緩存的不一致問題

那你可能會想,這是否表示,我應(yīng)該先讓緩存更新,之后再去更新數(shù)據(jù)庫呢?類似這樣:

updateRedis(key, data);//先更新緩存
updateMySQL();//再更新數(shù)據(jù)庫

這樣操作產(chǎn)生的問題更是顯而易見的,因為我們無法保證數(shù)據(jù)庫的更新成功,萬一數(shù)據(jù)庫更新失敗了,你緩存的數(shù)據(jù)就不只是臟數(shù)據(jù),而是錯誤數(shù)據(jù)了。

圖片圖片

你可能會想,是否我在更新數(shù)據(jù)庫失敗的時候做 Redis 回滾的操作能夠解決呢?這其實也是不靠譜的,因為我們也不能保證這個回滾的操作 100% 被成功執(zhí)行。

同時,在寫寫并發(fā)的場景下,同樣有類似的一致性問題,請看以下情況:

  • 線程 A 和線程 B 同時更新同這個數(shù)據(jù)。
  • 更新緩存的順序是先 A 后 B。
  • 更新數(shù)據(jù)庫的順序是先 B 后 A。

舉個例子。線程 A 希望把計數(shù)器置為 0,線程 B 希望置為 1。而按照以上場景,緩存確實被設(shè)置為 1,但數(shù)據(jù)庫卻被設(shè)置為 0。

所以通常情況下,更新緩存再更新數(shù)據(jù)庫是我們應(yīng)該避免使用的一種手段。

更新數(shù)據(jù)庫前刪除緩存的問題

那如果采取刪除緩存的策略呢?也就是說我們在更新數(shù)據(jù)庫的時候失效對應(yīng)的緩存,讓緩存在下次觸發(fā)讀請求時進(jìn)行更新,是否會更好呢?同樣地,針對在更新數(shù)據(jù)庫前和數(shù)據(jù)庫后這兩個刪除時機(jī),我們來比較下其差異。

最直觀的做法,我們可能會先讓緩存失效,然后去更新數(shù)據(jù)庫,代碼邏輯如下:

deleteRedis(key);//先刪除緩存讓緩存失效
updateMySQL();//再更新數(shù)據(jù)庫

這樣的邏輯看似沒有問題,畢竟刪除緩存后即便數(shù)據(jù)庫更新失敗了,也只是緩存上沒有數(shù)據(jù)而已。然后并發(fā)兩個寫請求過來,無論怎么樣的執(zhí)行順序,緩存最后的值也都是會被刪除的,也就是說在并發(fā)寫寫的請求下這樣的處理是沒問題的。

然而,這種處理在讀寫并發(fā)的場景下卻存在著隱患。

還是剛剛更新計數(shù)的例子。例如現(xiàn)在緩存的數(shù)據(jù)是 100,數(shù)據(jù)庫也是 100,這時候需要對此計數(shù)減 1,減成功后,數(shù)據(jù)庫應(yīng)該是 99。如果這之后觸發(fā)讀請求,緩存如果有效的話,里面應(yīng)該也要被更新為 99 才是正確的。

那么思考下這樣的請求情況:

  • 線程 A 更新這個數(shù)據(jù)的同時,線程 B 讀取這個數(shù)據(jù)。
  • 線程 A 成功刪除了緩存里的老數(shù)據(jù),這時候線程 B 查詢數(shù)據(jù)發(fā)現(xiàn)緩存失效。
  • 線程 A 更新數(shù)據(jù)庫成功。

時間

線程A(寫請求)

線程B(讀請求)

問題

T1

刪除緩存值



T2


1.讀取緩存數(shù)據(jù),緩存缺失,從數(shù)據(jù)庫讀取數(shù)據(jù)100


T3

更新數(shù)據(jù)庫中的數(shù)據(jù)X的值為99



T4


將數(shù)據(jù)100的值寫入緩存

此時緩存的值被顯式更新為100,但是實際上數(shù)據(jù)庫的值已經(jīng)是99了

可以看到,在讀寫并發(fā)的場景下,一樣會有不一致的問題。

針對這種場景,有個做法是所謂的“延遲雙刪策略”,就是說,既然可能因為讀請求把一個舊的值又寫回去,那么我在寫請求處理完之后,等到差不多的時間延遲再重新刪除這個緩存值。

時間

線程A(寫請求)

線程C(新的讀請求)

線程D(新的讀請求)

問題

T5

sleep(N)

緩存存在,讀取到緩存舊值100


其他線程可能在雙刪成功前讀到臟數(shù)據(jù)

T6

刪除緩存值




T7



緩存缺失,從數(shù)據(jù)庫讀取數(shù)據(jù)的最新值(99)


這種解決思路的關(guān)鍵在于對 N 的時間的判斷,如果 N 時間太短,線程 A 第二次刪除緩存的時間依舊早于線程 B 把臟數(shù)據(jù)寫回緩存的時間,那么相當(dāng)于做了無用功。而 N 如果設(shè)置得太長,那么在觸發(fā)雙刪之前,新請求看到的都是臟數(shù)據(jù)。

更新數(shù)據(jù)庫后刪除緩存

那如果我們把更新數(shù)據(jù)庫放在刪除緩存之前呢,問題是否解決?我們繼續(xù)從讀寫并發(fā)的場景看下去,有沒有類似的問題。

時間

線程A(寫請求)

線程B(讀請求)

線程C(讀請求)

潛在問題

T1

更新主庫 X = 99(原值 X = 100)




T2



讀取數(shù)據(jù),查詢到緩存還有數(shù)據(jù),返回100

線程C實際上讀取到了和數(shù)據(jù)庫不一致的數(shù)據(jù)

T3

刪除緩存




T4


查詢緩存,緩存缺失,查詢數(shù)據(jù)庫得到當(dāng)前值99



T5


將99寫入緩存



可以看到,大體上,采取先更新數(shù)據(jù)庫再刪除緩存的策略是沒有問題的,僅在更新數(shù)據(jù)庫成功到緩存刪除之間的時間差內(nèi)——[T2,T3)的窗口 ,可能會被別的線程讀取到老值。

而在開篇的時候我們說過,緩存不一致性的問題無法在客觀上完全消滅,因為我們無法保證數(shù)據(jù)庫和緩存的操作是一個事務(wù)里的,而我們能做到的只是盡量縮短不一致的時間窗口。

在更新數(shù)據(jù)庫后刪除緩存這個場景下,不一致窗口僅僅是 T2 到 T3 的時間,內(nèi)網(wǎng)狀態(tài)下通常不過 1ms,在大部分業(yè)務(wù)場景下我們都可以忽略不計。因為大部分情況下一個用戶的請求很難能再 1ms 內(nèi)快速發(fā)起第二次。

但是真實場景下,還是會有一個情況存在不一致的可能性,這個場景是讀線程發(fā)現(xiàn)緩存不存在,于是讀寫并發(fā)時,讀線程回寫進(jìn)去老值。并發(fā)情況如下:

時間

線程A(寫請求)

線程B(讀請求--緩存不存在場景)

潛在問題

T1


查詢緩存,緩存缺失,查詢數(shù)據(jù)庫得到當(dāng)前值100


T2

更新主庫 X = 99(原值 X = 100)



T3

刪除緩存



T4


將100寫入緩存

此時緩存的值被顯式更新為100,但是實際上數(shù)據(jù)庫的值已經(jīng)是99了

總的來說,這個不一致場景出現(xiàn)條件非常嚴(yán)格,因為并發(fā)量很大時,緩存不太可能不存在;如果并發(fā)很大,而緩存真的不存在,那么很可能是這時的寫場景很多,因為寫場景會刪除緩存。

所以待會我們會提到,寫場景很多時候?qū)嶋H上并不適合采取刪除策略。

總結(jié)四種更新策略

終上所述,我們對比了四個更新緩存的手段,做一個總結(jié)對比,其中應(yīng)對方案也提供參考,具體不做展開,如下表:

策略

并發(fā)場景

潛在問題

應(yīng)對方案

更新數(shù)據(jù)庫+更新緩存

寫+讀

線程A未更新完緩存之前,線程B的讀請求會短暫讀到舊值

可以忽略

寫+寫

更新數(shù)據(jù)庫的順序是先A后B,但更新緩存時順序是先B后A,數(shù)據(jù)庫和緩存數(shù)據(jù)不一致

分布式鎖(操作重)

更新緩存+更新數(shù)據(jù)庫

無并發(fā)

線程A還未更新完緩存但是更新數(shù)據(jù)庫可能失敗

利用MQ確認(rèn)數(shù)據(jù)庫更新成功(較復(fù)雜)

寫+寫

更新緩存的順序是先A后B,但更新數(shù)據(jù)庫時順序是先B后A

分布式鎖(操作很重)

刪除緩存值+更新數(shù)據(jù)庫

寫+讀

寫請求的線程A刪除了緩存在更新數(shù)據(jù)庫之前,這時候讀請求線程B到來,因為緩存缺失,則把當(dāng)前數(shù)據(jù)讀取出來放到緩存,而后線程A更新成功了數(shù)據(jù)庫

延遲雙刪(但是延遲的時間不好估計,且延遲的過程中依舊有不一致的時間窗口)

更新數(shù)據(jù)庫+刪除緩存值

寫+讀(緩存命中)

線程A完成數(shù)據(jù)庫更新成功后,尚未刪除緩存,線程B有并發(fā)讀請求會讀到舊的臟數(shù)據(jù)

可以忽略

寫+讀(緩存不命中)

讀請求不命中緩存,寫請求處理完之后讀請求才回寫緩存,此時緩存不一致

分布式鎖(操作重)

從一致性的角度來看,采取更新數(shù)據(jù)庫后刪除緩存值,是更為適合的策略。因為出現(xiàn)不一致的場景的條件更為苛刻,概率相比其他方案更低。

那么是否更新緩存這個策略就一無是處呢?不是的!

刪除緩存值意味著對應(yīng)的 Key 會失效,那么這時候讀請求都會打到數(shù)據(jù)庫。如果這個數(shù)據(jù)的寫操作非常頻繁,就會導(dǎo)致緩存的作用變得非常小。而如果這時候某些 Key 還是非常大的熱 Key,就可能因為扛不住數(shù)據(jù)量而導(dǎo)致系統(tǒng)不可用。

如下圖所示:

圖片

刪除策略頻繁的緩存失效導(dǎo)致讀請求無法利用緩存

所以做個簡單總結(jié),足以適應(yīng)絕大部分的互聯(lián)網(wǎng)開發(fā)場景的決策:

  • 針對大部分讀多寫少場景,建議選擇更新數(shù)據(jù)庫后刪除緩存的策略。
  • 針對讀寫相當(dāng)或者寫多讀少的場景,建議選擇更新數(shù)據(jù)庫后更新緩存的策略。

4.最終一致性如何保證?

緩存設(shè)置過期時間

第一個方法便是我們上面提到的,當(dāng)我們無法確定 MySQL 更新完成后,緩存的更新/刪除一定能成功,例如 Redis 掛了導(dǎo)致寫入失敗了,或者當(dāng)時網(wǎng)絡(luò)出現(xiàn)故障,更常見的是服務(wù)當(dāng)時剛好發(fā)生重啟了,沒有執(zhí)行這一步的代碼。

這些時候 MySQL 的數(shù)據(jù)就無法刷到 Redis 了。為了避免這種不一致性永久存在,使用緩存的時候,我們必須要給緩存設(shè)置一個過期時間,例如 1 分鐘,這樣即使出現(xiàn)了更新 Redis 失敗的極端場景,不一致的時間窗口最多也只是 1 分鐘。

這是我們最終一致性的兜底方案,萬一出現(xiàn)任何情況的不一致問題,最后都能通過緩存失效后重新查詢數(shù)據(jù)庫,然后回寫到緩存,來做到緩存與數(shù)據(jù)庫的最終一致。

5.如何減少緩存刪除/更新的失?。?/h2>

萬一刪除緩存這一步因為服務(wù)重啟沒有執(zhí)行,或者 Redis 臨時不可用導(dǎo)致刪除緩存失敗了,就會有一個較長的時間(緩存的剩余過期時間)是數(shù)據(jù)不一致的。

那我們有沒有什么手段來減少這種不一致的情況出現(xiàn)呢?這時候借助一個可靠的消息中間件就是一個不錯的選擇。

因為消息中間件有 ATLEAST-ONCE 的機(jī)制,如下圖所示。

圖片圖片

我們把刪除 Redis 的請求以消費 MQ 消息的手段去失效對應(yīng)的 Key 值,如果 Redis 真的存在異常導(dǎo)致無法刪除成功,我們依舊可以依靠 MQ 的重試機(jī)制來讓最終 Redis 對應(yīng)的 Key 失效。

而你們或許會問,極端場景下,是否存在更新數(shù)據(jù)庫后 MQ 消息沒發(fā)送成功,或者沒機(jī)會發(fā)送出去機(jī)器就重啟的情況?

這個場景的確比較麻煩,如果 MQ 使用的是 RocketMQ,我們可以借助 RocketMQ 的事務(wù)消息,來讓刪除緩存的消息最終一定發(fā)送出去。而如果你沒有使用 RocketMQ,或者你使用的消息中間件并沒有事務(wù)消息的特性,則可以采取消息表的方式讓更新數(shù)據(jù)庫和發(fā)送消息一起成功。事實上這個話題比較大了,我們不在這里展開。

6.如何處理復(fù)雜的多緩存場景?

有些時候,真實的緩存場景并不是數(shù)據(jù)庫中的一個記錄對應(yīng)一個 Key 這么簡單,有可能一個數(shù)據(jù)庫記錄的更新會牽扯到多個 Key 的更新。還有另外一個場景是,更新不同的數(shù)據(jù)庫的記錄時可能需要更新同一個 Key 值,這常見于一些 App 首頁數(shù)據(jù)的緩存。

我們以一個數(shù)據(jù)庫記錄對應(yīng)多個 Key 的場景來舉例。

假如系統(tǒng)設(shè)計上我們緩存了一個粉絲的主頁信息、主播打賞榜 TOP10 的粉絲、單日 TOP 100 的粉絲等多個信息。如果這個粉絲注銷了,或者這個粉絲觸發(fā)了打賞的行為,上面多個 Key 可能都需要更新。只是一個打賞的記錄,你可能就要做:

updateMySQL();//更新數(shù)據(jù)庫一條記錄
deleteRedisKey1();//失效主頁信息的緩存
updateRedisKey2();//更新打賞榜TOP10
deleteRedisKey3();//更新單日打賞榜TOP100

這就涉及多個 Redis 的操作,每一步都可能失敗,影響到后面的更新。甚至從系統(tǒng)設(shè)計上,更新數(shù)據(jù)庫可能是單獨的一個服務(wù),而這幾個不同的 Key 的緩存維護(hù)卻在不同的 3 個微服務(wù)中,這就大大增加了系統(tǒng)的復(fù)雜度和提高了緩存操作失敗的可能性。最可怕的是,操作更新記錄的地方很大概率不只在一個業(yè)務(wù)邏輯中,而是散發(fā)在系統(tǒng)各個零散的位置。

針對這個場景,解決方案和上文提到的保證最終一致性的操作一樣,就是把更新緩存的操作以 MQ 消息的方式發(fā)送出去,由不同的系統(tǒng)或者專門的一個系統(tǒng)進(jìn)行訂閱,而做聚合的操作。如下圖:

圖片圖片

不同業(yè)務(wù)系統(tǒng)訂閱 MQ 消息單獨維護(hù)各自的緩存 Key

7.通過訂閱 MySQL binlog 的方式處理緩存

上面講到的 MQ 處理方式需要業(yè)務(wù)代碼里面顯式地發(fā)送 MQ 消息。還有一種優(yōu)雅的方式便是訂閱 MySQL 的 binlog,監(jiān)聽數(shù)據(jù)的真實變化情況以處理相關(guān)的緩存。

例如剛剛提到的例子中,如果粉絲又觸發(fā)打賞了,這時候我們利用 binlog 表監(jiān)聽是能及時發(fā)現(xiàn)的,發(fā)現(xiàn)后就能集中處理了,而且無論是在什么系統(tǒng)什么位置去更新數(shù)據(jù),都能做到集中處理。

目前業(yè)界類似的產(chǎn)品有 Canal,具體的操作圖如下:

圖片圖片

利用 Canel 訂閱數(shù)據(jù)庫 binlog 變更從而發(fā)出 MQ 消息,讓一個專門消費者服務(wù)維護(hù)所有相關(guān) Key 的緩存操作

到這里,針對大型系統(tǒng)緩存設(shè)計如何保證最終一致性,我們已經(jīng)從策略、場景、操作方案等角度進(jìn)行了細(xì)致的講述,希望能對你起到幫助。


責(zé)任編輯:武曉燕 來源: 碼哥跳動
相關(guān)推薦

2024-04-11 13:45:14

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

2020-09-04 06:32:08

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

2021-09-08 11:03:13

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

2023-04-13 08:15:47

Redis緩存一致性

2024-11-14 07:10:00

2022-09-16 09:46:42

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

2020-01-02 09:06:23

微服務(wù)數(shù)據(jù)框架

2022-09-06 15:30:20

緩存一致性

2021-06-11 09:21:58

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

2023-11-06 09:06:54

分布式一致性數(shù)據(jù)

2017-09-04 14:46:10

分布式事務(wù)問題

2020-07-16 07:30:15

數(shù)據(jù)庫SQL技術(shù)

2016-11-29 09:00:19

分布式數(shù)據(jù)一致性CAS

2022-10-08 00:00:09

數(shù)據(jù)庫緩存系統(tǒng)

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2022-05-31 08:37:59

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

2024-04-10 10:34:34

Cache系統(tǒng)GPU

2025-04-27 08:52:21

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

2020-09-03 09:45:38

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

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫
點贊
收藏

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