精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

緩存和數(shù)據(jù)庫一致性問題,看這篇就夠了

存儲(chǔ)
假設(shè)我們采用「先更新數(shù)據(jù)庫,再更新緩存」的方案,并且兩步都可以「成功執(zhí)行」的前提下,如果存在并發(fā),情況會(huì)是怎樣的呢?

[[422528]]

你好,我是 Kaito。

如何保證緩存和數(shù)據(jù)庫一致性,這是一個(gè)老生常談的話題了。

但很多人對這個(gè)問題,依舊有很多疑惑:

  • 到底是更新緩存還是刪緩存?
  • 到底選擇先更新數(shù)據(jù)庫,再刪除緩存,還是先刪除緩存,再更新數(shù)據(jù)庫?
  • 為什么要引入消息隊(duì)列保證一致性?
  • 延遲雙刪會(huì)有什么問題?到底要不要用?
  • ...

這篇文章,我們就來把這些問題講清楚。

這篇文章干貨很多,希望你可以耐心讀完。

引入緩存提高性能

我們從最簡單的場景開始講起。

如果你的業(yè)務(wù)處于起步階段,流量非常小,那無論是讀請求還是寫請求,直接操作數(shù)據(jù)庫即可,這時(shí)你的架構(gòu)模型是這樣的:

但隨著業(yè)務(wù)量的增長,你的項(xiàng)目請求量越來越大,這時(shí)如果每次都從數(shù)據(jù)庫中讀數(shù)據(jù),那肯定會(huì)有性能問題。

這個(gè)階段通常的做法是,引入「緩存」來提高讀性能,架構(gòu)模型就變成了這樣:

當(dāng)下優(yōu)秀的緩存中間件,當(dāng)屬 Redis 莫屬,它不僅性能非常高,還提供了很多友好的數(shù)據(jù)類型,可以很好地滿足我們的業(yè)務(wù)需求。

但引入緩存之后,你就會(huì)面臨一個(gè)問題:之前數(shù)據(jù)只存在數(shù)據(jù)庫中,現(xiàn)在要放到緩存中讀取,具體要怎么存呢?

最簡單直接的方案是「全量數(shù)據(jù)刷到緩存中」:

  • 數(shù)據(jù)庫的數(shù)據(jù),全量刷入緩存(不設(shè)置失效時(shí)間)
  • 寫請求只更新數(shù)據(jù)庫,不更新緩存
  • 啟動(dòng)一個(gè)定時(shí)任務(wù),定時(shí)把數(shù)據(jù)庫的數(shù)據(jù),更新到緩存中

這個(gè)方案的優(yōu)點(diǎn)是,所有讀請求都可以直接「命中」緩存,不需要再查數(shù)據(jù)庫,性能非常高。

但缺點(diǎn)也很明顯,有 2 個(gè)問題:

  • 緩存利用率低:不經(jīng)常訪問的數(shù)據(jù),還一直留在緩存中
  • 數(shù)據(jù)不一致:因?yàn)槭恰付〞r(shí)」刷新緩存,緩存和數(shù)據(jù)庫存在不一致(取決于定時(shí)任務(wù)的執(zhí)行頻率)

所以,這種方案一般更適合業(yè)務(wù)「體量小」,且對數(shù)據(jù)一致性要求不高的業(yè)務(wù)場景。

那如果我們的業(yè)務(wù)體量很大,怎么解決這 2 個(gè)問題呢?

緩存利用率和一致性問題

先來看第一個(gè)問題,如何提高緩存利用率?

想要緩存利用率「最大化」,我們很容易想到的方案是,緩存中只保留最近訪問的「熱數(shù)據(jù)」。但具體要怎么做呢?

我們可以這樣優(yōu)化:

  • 寫請求依舊只寫數(shù)據(jù)庫
  • 讀請求先讀緩存,如果緩存不存在,則從數(shù)據(jù)庫讀取,并重建緩存
  • 同時(shí),寫入緩存中的數(shù)據(jù),都設(shè)置失效時(shí)間

這樣一來,緩存中不經(jīng)常訪問的數(shù)據(jù),隨著時(shí)間的推移,都會(huì)逐漸「過期」淘汰掉,最終緩存中保留的,都是經(jīng)常被訪問的「熱數(shù)據(jù)」,緩存利用率得以最大化。

再來看數(shù)據(jù)一致性問題。

要想保證緩存和數(shù)據(jù)庫「實(shí)時(shí)」一致,那就不能再用定時(shí)任務(wù)刷新緩存了。

所以,當(dāng)數(shù)據(jù)發(fā)生更新時(shí),我們不僅要操作數(shù)據(jù)庫,還要一并操作緩存。具體操作就是,修改一條數(shù)據(jù)時(shí),不僅要更新數(shù)據(jù)庫,也要連帶緩存一起更新。

但數(shù)據(jù)庫和緩存都更新,又存在先后問題,那對應(yīng)的方案就有 2 個(gè):

  1. 先更新緩存,后更新數(shù)據(jù)庫
  2. 先更新數(shù)據(jù)庫,后更新緩存

哪個(gè)方案更好呢?

先不考慮并發(fā)問題,正常情況下,無論誰先誰后,都可以讓兩者保持一致,但現(xiàn)在我們需要重點(diǎn)考慮「異常」情況。

因?yàn)椴僮鞣譃閮刹剑敲淳秃苡锌赡艽嬖凇傅谝徊匠晒Α⒌诙绞 沟那闆r發(fā)生。

這 2 種方案我們一個(gè)個(gè)來分析。

1) 先更新緩存,后更新數(shù)據(jù)庫

如果緩存更新成功了,但數(shù)據(jù)庫更新失敗,那么此時(shí)緩存中是最新值,但數(shù)據(jù)庫中是「舊值」。

雖然此時(shí)讀請求可以命中緩存,拿到正確的值,但是,一旦緩存「失效」,就會(huì)從數(shù)據(jù)庫中讀取到「舊值」,重建緩存也是這個(gè)舊值。

這時(shí)用戶會(huì)發(fā)現(xiàn)自己之前修改的數(shù)據(jù)又「變回去」了,對業(yè)務(wù)造成影響。

2) 先更新數(shù)據(jù)庫,后更新緩存

如果數(shù)據(jù)庫更新成功了,但緩存更新失敗,那么此時(shí)數(shù)據(jù)庫中是最新值,緩存中是「舊值」。

之后的讀請求讀到的都是舊數(shù)據(jù),只有當(dāng)緩存「失效」后,才能從數(shù)據(jù)庫中得到正確的值。

這時(shí)用戶會(huì)發(fā)現(xiàn),自己剛剛修改了數(shù)據(jù),但卻看不到變更,一段時(shí)間過后,數(shù)據(jù)才變更過來,對業(yè)務(wù)也會(huì)有影響。

可見,無論誰先誰后,但凡后者發(fā)生異常,就會(huì)對業(yè)務(wù)造成影響。那怎么解決這個(gè)問題呢?

別急,后面我會(huì)詳細(xì)給出對應(yīng)的解決方案。

我們繼續(xù)分析,除了操作失敗問題,還有什么場景會(huì)影響數(shù)據(jù)一致性?

這里我們還需要重點(diǎn)關(guān)注:并發(fā)問題。

并發(fā)引發(fā)的一致性問題

假設(shè)我們采用「先更新數(shù)據(jù)庫,再更新緩存」的方案,并且兩步都可以「成功執(zhí)行」的前提下,如果存在并發(fā),情況會(huì)是怎樣的呢?

有線程 A 和線程 B 兩個(gè)線程,需要更新「同一條」數(shù)據(jù),會(huì)發(fā)生這樣的場景:

  1. 線程 A 更新數(shù)據(jù)庫(X = 1)
  2. 線程 B 更新數(shù)據(jù)庫(X = 2)
  3. 線程 B 更新緩存(X = 2)
  4. 線程 A 更新緩存(X = 1)

最終 X 的值在緩存中是 1,在數(shù)據(jù)庫中是 2,發(fā)生不一致。

也就是說,A 雖然先于 B 發(fā)生,但 B 操作數(shù)據(jù)庫和緩存的時(shí)間,卻要比 A 的時(shí)間短,執(zhí)行時(shí)序發(fā)生「錯(cuò)亂」,最終這條數(shù)據(jù)結(jié)果是不符合預(yù)期的。

同樣地,采用「先更新緩存,再更新數(shù)據(jù)庫」的方案,也會(huì)有類似問題,這里不再詳述。

除此之外,我們從「緩存利用率」的角度來評估這個(gè)方案,也是不太推薦的。

這是因?yàn)槊看螖?shù)據(jù)發(fā)生變更,都「無腦」更新緩存,但是緩存中的數(shù)據(jù)不一定會(huì)被「馬上讀取」,這就會(huì)導(dǎo)致緩存中可能存放了很多不常訪問的數(shù)據(jù),浪費(fèi)緩存資源。

而且很多情況下,寫到緩存中的值,并不是與數(shù)據(jù)庫中的值一一對應(yīng)的,很有可能是先查詢數(shù)據(jù)庫,再經(jīng)過一系列「計(jì)算」得出一個(gè)值,才把這個(gè)值才寫到緩存中。

由此可見,這種「更新數(shù)據(jù)庫 + 更新緩存」的方案,不僅緩存利用率不高,還會(huì)造成機(jī)器性能的浪費(fèi)。

所以此時(shí)我們需要考慮另外一種方案:刪除緩存。

刪除緩存可以保證一致性嗎?

刪除緩存對應(yīng)的方案也有 2 種:

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

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

經(jīng)過前面的分析我們已經(jīng)得知,但凡「第二步」操作失敗,都會(huì)導(dǎo)致數(shù)據(jù)不一致。

這里我不再詳述具體場景,你可以按照前面的思路推演一下,就可以看到依舊存在數(shù)據(jù)不一致的情況。

這里我們重點(diǎn)來看「并發(fā)」問題。

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

如果有 2 個(gè)線程要并發(fā)「讀寫」數(shù)據(jù),可能會(huì)發(fā)生以下場景:

  • 線程 A 要更新 X = 2(原值 X = 1)
  • 線程 A 先刪除緩存
  • 線程 B 讀緩存,發(fā)現(xiàn)不存在,從數(shù)據(jù)庫中讀取到舊值(X = 1)
  • 線程 A 將新值寫入數(shù)據(jù)庫(X = 2)
  • 線程 B 將舊值寫入緩存(X = 1)

最終 X 的值在緩存中是 1(舊值),在數(shù)據(jù)庫中是 2(新值),發(fā)生不一致。

可見,先刪除緩存,后更新數(shù)據(jù)庫,當(dāng)發(fā)生「讀+寫」并發(fā)時(shí),還是存在數(shù)據(jù)不一致的情況。

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

依舊是 2 個(gè)線程并發(fā)「讀寫」數(shù)據(jù):

  • 緩存中 X 不存在(數(shù)據(jù)庫 X = 1)
  • 線程 A 讀取數(shù)據(jù)庫,得到舊值(X = 1)
  • 線程 B 更新數(shù)據(jù)庫(X = 2)
  • 線程 B 刪除緩存
  • 線程 A 將舊值寫入緩存(X = 1)

最終 X 的值在緩存中是 1(舊值),在數(shù)據(jù)庫中是 2(新值),也發(fā)生不一致。

這種情況「理論」來說是可能發(fā)生的,但實(shí)際真的有可能發(fā)生嗎?

其實(shí)概率「很低」,這是因?yàn)樗仨殱M足 3 個(gè)條件:

  • 緩存剛好已失效
  • 讀請求 + 寫請求并發(fā)
  • 更新數(shù)據(jù)庫 + 刪除緩存的時(shí)間(步驟 3-4),要比讀數(shù)據(jù)庫 + 寫緩存時(shí)間短(步驟 2 和 5)

仔細(xì)想一下,條件 3 發(fā)生的概率其實(shí)是非常低的。

因?yàn)閷憯?shù)據(jù)庫一般會(huì)先「加鎖」,所以寫數(shù)據(jù)庫,通常是要比讀數(shù)據(jù)庫的時(shí)間更長的。

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

所以,我們應(yīng)該采用這種方案,來操作數(shù)據(jù)庫和緩存。

好,解決了并發(fā)問題,我們繼續(xù)來看前面遺留的,第二步執(zhí)行「失敗」導(dǎo)致數(shù)據(jù)不一致的問題。

如何保證兩步都執(zhí)行成功?

前面我們分析到,無論是更新緩存還是刪除緩存,只要第二步發(fā)生失敗,那么就會(huì)導(dǎo)致數(shù)據(jù)庫和緩存不一致。

保證第二步成功執(zhí)行,就是解決問題的關(guān)鍵。

想一下,程序在執(zhí)行過程中發(fā)生異常,最簡單的解決辦法是什么?

答案是:重試。

是的,其實(shí)這里我們也可以這樣做。

無論是先操作緩存,還是先操作數(shù)據(jù)庫,但凡后者執(zhí)行失敗了,我們就可以發(fā)起重試,盡可能地去做「補(bǔ)償」。

那這是不是意味著,只要執(zhí)行失敗,我們「無腦重試」就可以了呢?

答案是否定的。現(xiàn)實(shí)情況往往沒有想的這么簡單,失敗后立即重試的問題在于:

  • 立即重試很大概率「還會(huì)失敗」
  • 「重試次數(shù)」設(shè)置多少才合理?
  • 重試會(huì)一直「占用」這個(gè)線程資源,無法服務(wù)其它客戶端請求

看到了么,雖然我們想通過重試的方式解決問題,但這種「同步」重試的方案依舊不嚴(yán)謹(jǐn)。

那更好的方案應(yīng)該怎么做?

答案是:異步重試。什么是異步重試?

其實(shí)就是把重試請求寫到「消息隊(duì)列」中,然后由專門的消費(fèi)者來重試,直到成功。

或者更直接的做法,為了避免第二步執(zhí)行失敗,我們可以把操作緩存這一步,直接放到消息隊(duì)列中,由消費(fèi)者來操作緩存。

到這里你可能會(huì)問,寫消息隊(duì)列也有可能會(huì)失敗啊?而且,引入消息隊(duì)列,這又增加了更多的維護(hù)成本,這樣做值得嗎?

這個(gè)問題很好,但我們思考這樣一個(gè)問題:如果在執(zhí)行失敗的線程中一直重試,還沒等執(zhí)行成功,此時(shí)如果項(xiàng)目「重啟」了,那這次重試請求也就「丟失」了,那這條數(shù)據(jù)就一直不一致了。

所以,這里我們必須把重試或第二步操作放到另一個(gè)「服務(wù)」中,這個(gè)服務(wù)用「消息隊(duì)列」最為合適。這是因?yàn)橄㈥?duì)列的特性,正好符合我們的需求:

  • 消息隊(duì)列保證可靠性:寫到隊(duì)列中的消息,成功消費(fèi)之前不會(huì)丟失(重啟項(xiàng)目也不擔(dān)心)
  • 消息隊(duì)列保證消息成功投遞:下游從隊(duì)列拉取消息,成功消費(fèi)后才會(huì)刪除消息,否則還會(huì)繼續(xù)投遞消息給消費(fèi)者(符合我們重試的場景)

至于寫隊(duì)列失敗和消息隊(duì)列的維護(hù)成本問題:

  • 寫隊(duì)列失敗:操作緩存和寫消息隊(duì)列,「同時(shí)失敗」的概率其實(shí)是很小的
  • 維護(hù)成本:我們項(xiàng)目中一般都會(huì)用到消息隊(duì)列,維護(hù)成本并沒有新增很多

所以,引入消息隊(duì)列來解決這個(gè)問題,是比較合適的。這時(shí)架構(gòu)模型就變成了這樣:

那如果你確實(shí)不想在應(yīng)用中去寫消息隊(duì)列,是否有更簡單的方案,同時(shí)又可以保證一致性呢?

方案還是有的,這就是近幾年比較流行的解決方案:訂閱數(shù)據(jù)庫變更日志,再操作緩存。

具體來講就是,我們的業(yè)務(wù)應(yīng)用在修改數(shù)據(jù)時(shí),「只需」修改數(shù)據(jù)庫,無需操作緩存。

那什么時(shí)候操作緩存呢?這就和數(shù)據(jù)庫的「變更日志」有關(guān)了。

拿 MySQL 舉例,當(dāng)一條數(shù)據(jù)發(fā)生修改時(shí),MySQL 就會(huì)產(chǎn)生一條變更日志(Binlog),我們可以訂閱這個(gè)日志,拿到具體操作的數(shù)據(jù),然后再根據(jù)這條數(shù)據(jù),去刪除對應(yīng)的緩存。

訂閱變更日志,目前也有了比較成熟的開源中間件,例如阿里的 canal,使用這種方案的優(yōu)點(diǎn)在于:

  • 無需考慮寫消息隊(duì)列失敗情況:只要寫 MySQL 成功,Binlog 肯定會(huì)有
  • 自動(dòng)投遞到下游隊(duì)列:canal 自動(dòng)把數(shù)據(jù)庫變更日志「投遞」給下游的消息隊(duì)列

當(dāng)然,與此同時(shí),我們需要投入精力去維護(hù) canal 的高可用和穩(wěn)定性。

如果你有留意觀察很多數(shù)據(jù)庫的特性,就會(huì)發(fā)現(xiàn)其實(shí)很多數(shù)據(jù)庫都逐漸開始提供「訂閱變更日志」的功能了,相信不遠(yuǎn)的將來,我們就不用通過中間件來拉取日志,自己寫程序就可以訂閱變更日志了,這樣可以進(jìn)一步簡化流程。

至此,我們可以得出結(jié)論,想要保證數(shù)據(jù)庫和緩存一致性,推薦采用「先更新數(shù)據(jù)庫,再刪除緩存」方案,并配合「消息隊(duì)列」或「訂閱變更日志」的方式來做。

主從庫延遲和延遲雙刪問題

到這里,還有 2 個(gè)問題,是我們沒有重點(diǎn)分析過的。

第一個(gè)問題,還記得前面講到的「先刪除緩存,再更新數(shù)據(jù)庫」方案,導(dǎo)致不一致的場景么?

這里我再把例子拿過來讓你復(fù)習(xí)一下:

2 個(gè)線程要并發(fā)「讀寫」數(shù)據(jù),可能會(huì)發(fā)生以下場景:

  • 線程 A 要更新 X = 2(原值 X = 1)
  • 線程 A 先刪除緩存
  • 線程 B 讀緩存,發(fā)現(xiàn)不存在,從數(shù)據(jù)庫中讀取到舊值(X = 1)
  • 線程 A 將新值寫入數(shù)據(jù)庫(X = 2)
  • 線程 B 將舊值寫入緩存(X = 1)

最終 X 的值在緩存中是 1(舊值),在數(shù)據(jù)庫中是 2(新值),發(fā)生不一致。

第二個(gè)問題:是關(guān)于「讀寫分離 + 主從復(fù)制延遲」情況下,緩存和數(shù)據(jù)庫一致性的問題。

在「先更新數(shù)據(jù)庫,再刪除緩存」方案下,「讀寫分離 + 主從庫延遲」其實(shí)也會(huì)導(dǎo)致不一致:

  • 線程 A 更新主庫 X = 2(原值 X = 1)
  • 線程 A 刪除緩存
  • 線程 B 查詢緩存,沒有命中,查詢「從庫」得到舊值(從庫 X = 1)
  • 從庫「同步」完成(主從庫 X = 2)
  • 線程 B 將「舊值」寫入緩存(X = 1)

最終 X 的值在緩存中是 1(舊值),在主從庫中是 2(新值),也發(fā)生不一致。

看到了么?這 2 個(gè)問題的核心在于:緩存都被回種了「舊值」。

那怎么解決這類問題呢?

最有效的辦法就是,把緩存刪掉。

但是,不能立即刪,而是需要「延遲刪」,這就是業(yè)界給出的方案:緩存延遲雙刪策略。

按照延時(shí)雙刪策略,這 2 個(gè)問題的解決方案是這樣的:

解決第一個(gè)問題:在線程 A 刪除緩存、更新完數(shù)據(jù)庫之后,先「休眠一會(huì)」,再「刪除」一次緩存。

解決第二個(gè)問題:線程 A 可以生成一條「延時(shí)消息」,寫到消息隊(duì)列中,消費(fèi)者延時(shí)「刪除」緩存。

這兩個(gè)方案的目的,都是為了把緩存清掉,這樣一來,下次就可以從數(shù)據(jù)庫讀取到最新值,寫入緩存。

但問題來了,這個(gè)「延遲刪除」緩存,延遲時(shí)間到底設(shè)置要多久呢?

  • 問題1:延遲時(shí)間要大于「主從復(fù)制」的延遲時(shí)間
  • 問題2:延遲時(shí)間要大于線程 B 讀取數(shù)據(jù)庫 + 寫入緩存的時(shí)間

但是,這個(gè)時(shí)間在分布式和高并發(fā)場景下,其實(shí)是很難評估的。

很多時(shí)候,我們都是憑借經(jīng)驗(yàn)大致估算這個(gè)延遲時(shí)間,例如延遲 1-5s,只能盡可能地降低不一致的概率。

所以你看,采用這種方案,也只是盡可能保證一致性而已,極端情況下,還是有可能發(fā)生不一致。

所以實(shí)際使用中,我還是建議你采用「先更新數(shù)據(jù)庫,再刪除緩存」的方案,同時(shí),要盡可能地保證「主從復(fù)制」不要有太大延遲,降低出問題的概率。

可以做到強(qiáng)一致嗎?

看到這里你可能會(huì)想,這些方案還是不夠完美,我就想讓緩存和數(shù)據(jù)庫「強(qiáng)一致」,到底能不能做到呢?

其實(shí)很難。

要想做到強(qiáng)一致,最常見的方案是 2PC、3PC、Paxos、Raft 這類一致性協(xié)議,但它們的性能往往比較差,而且這些方案也比較復(fù)雜,還要考慮各種容錯(cuò)問題。

相反,這時(shí)我們換個(gè)角度思考一下,我們引入緩存的目的是什么?

沒錯(cuò),性能。

一旦我們決定使用緩存,那必然要面臨一致性問題。性能和一致性就像天平的兩端,無法做到都滿足要求。

而且,就拿我們前面講到的方案來說,當(dāng)操作數(shù)據(jù)庫和緩存完成之前,只要有其它請求可以進(jìn)來,都有可能查到「中間狀態(tài)」的數(shù)據(jù)。

所以如果非要追求強(qiáng)一致,那必須要求所有更新操作完成之前期間,不能有「任何請求」進(jìn)來。

雖然我們可以通過加「分布鎖」的方式來實(shí)現(xiàn),但我們要付出的代價(jià),很可能會(huì)超過引入緩存帶來的性能提升。

所以,既然決定使用緩存,就必須容忍「一致性」問題,我們只能盡可能地去降低問題出現(xiàn)的概率。

同時(shí)我們也要知道,緩存都是有「失效時(shí)間」的,就算在這期間存在短期不一致,我們依舊有失效時(shí)間來兜底,這樣也能達(dá)到最終一致。

總結(jié)

好了,總結(jié)一下這篇文章的重點(diǎn)。

1、想要提高應(yīng)用的性能,可以引入「緩存」來解決

2、引入緩存后,需要考慮緩存和數(shù)據(jù)庫一致性問題,可選的方案有:「更新數(shù)據(jù)庫 + 更新緩存」、「更新數(shù)據(jù)庫 + 刪除緩存」

3、更新數(shù)據(jù)庫 + 更新緩存方案,在「并發(fā)」場景下無法保證緩存和數(shù)據(jù)一致性,且存在「緩存資源浪費(fèi)」和「機(jī)器性能浪費(fèi)」的情況發(fā)生

4、在更新數(shù)據(jù)庫 + 刪除緩存的方案中,「先刪除緩存,再更新數(shù)據(jù)庫」在「并發(fā)」場景下依舊有數(shù)據(jù)不一致問題,解決方案是「延遲雙刪」,但這個(gè)延遲時(shí)間很難評估,所以推薦用「先更新數(shù)據(jù)庫,再刪除緩存」的方案

5、在「先更新數(shù)據(jù)庫,再刪除緩存」方案下,為了保證兩步都成功執(zhí)行,需配合「消息隊(duì)列」或「訂閱變更日志」的方案來做,本質(zhì)是通過「重試」的方式保證數(shù)據(jù)一致性

6、在「先更新數(shù)據(jù)庫,再刪除緩存」方案下,「讀寫分離 + 主從庫延遲」也會(huì)導(dǎo)致緩存和數(shù)據(jù)庫不一致,緩解此問題的方案是「延遲雙刪」,憑借經(jīng)驗(yàn)發(fā)送「延遲消息」到隊(duì)列中,延遲刪除緩存,同時(shí)也要控制主從庫延遲,盡可能降低不一致發(fā)生的概率

后記

本以為這個(gè)老生常談的話題,寫起來很好寫,沒想到在寫的過程中,還是挖到了很多之前沒有深度思考過的細(xì)節(jié)。

在這里我也分享 4 點(diǎn)心得給你:

1、性能和一致性不能同時(shí)滿足,為了性能考慮,通常會(huì)采用「最終一致性」的方案

2、掌握緩存和數(shù)據(jù)庫一致性問題,核心問題有 3 點(diǎn):緩存利用率、并發(fā)、緩存 + 數(shù)據(jù)庫一起成功問題

3、失敗場景下要保證一致性,常見手段就是「重試」,同步重試會(huì)影響吞吐量,所以通常會(huì)采用異步重試的方案

4、訂閱變更日志的思想,本質(zhì)是把權(quán)威數(shù)據(jù)源(例如 MySQL)當(dāng)做 leader 副本,讓其它異質(zhì)系統(tǒng)(例如 Redis / Elasticsearch)成為它的 follower 副本,通過同步變更日志的方式,保證 leader 和 follower 之間保持一致

很多一致性問題,都會(huì)采用這些方案來解決,希望我的這些心得對你有所啟發(fā)。

本文轉(zhuǎn)載自微信公眾號「水滴與銀彈」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系水滴與銀彈公眾號。

 

責(zé)任編輯:武曉燕 來源: 水滴與銀彈
相關(guān)推薦

2020-09-04 06:32:08

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

2024-04-11 13:45:14

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

2024-11-14 07:10:00

2024-10-28 12:41:25

2022-03-29 10:39:10

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

2024-11-07 22:57:30

2022-09-06 15:30:20

緩存一致性

2022-09-16 09:46:42

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

2022-10-08 00:00:09

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

2021-12-01 08:26:27

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

2016-11-29 09:00:19

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

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2023-04-13 08:15:47

Redis緩存一致性

2021-06-11 09:21:58

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

2021-09-30 07:59:06

zookeeper一致性算法CAP

2019-08-16 09:41:56

UDP協(xié)議TCP

2020-10-13 07:44:40

緩存雪崩 穿透

2022-08-11 07:55:05

數(shù)據(jù)庫Mysql

2025-06-16 02:11:00

2021-05-07 07:52:51

Java并發(fā)編程
點(diǎn)贊
收藏

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

国产精品情侣自拍| 日本不卡视频在线| 日韩美女一区二区三区| 国产在线视频综合| 日韩毛片在线一区二区毛片| 久久久久一区| 欧美成人剧情片在线观看| 国产精品久久久久久亚洲色| 蜜桃成人精品| 有坂深雪av一区二区精品| 久久久久久草| 永久免费看mv网站入口| 欧美另类中文字幕| 高潮白浆女日韩av免费看| 亚洲欧美日韩综合一区| 亚洲爱情岛论坛永久| 日韩大片在线| 欧美不卡在线视频| 日本美女高潮视频| 日韩中文字幕免费在线观看| 午夜一区二区三区不卡视频| www国产精品视频| 精品国产人妻一区二区三区| 日韩福利影视| 黑人巨大精品欧美一区二区| 国产91av视频在线观看| 午夜福利视频一区二区| 精品一二三四区| 国产亚洲免费的视频看| 樱花草www在线| 综合久久2023| 一区二区久久久| 亚洲精品中文字幕乱码三区不卡 | 日本亚洲欧美| 国产精品一区二区视频| 国产成人一区二区三区小说| 国产精品99精品| 久久精品国内一区二区三区水蜜桃| 亚洲精品久久在线| 4438x全国最大成人| 久久精品国产精品亚洲毛片| 日本久久电影网| 99视频在线免费播放| 性xxxfreexxxx性欧美| 国产精品美女久久久久av爽李琼| 狼狼综合久久久久综合网| 黄色a在线观看| 亚洲视频精品| 久久天天躁狠狠躁夜夜av| 91香蕉国产线在线观看| 亚洲精品粉嫩美女一区| 欧美日韩中文字幕日韩欧美| 精品丰满人妻无套内射| 国产嫩草在线视频| 久久中文字幕电影| 国产91视觉| 国产ts人妖调教重口男| 一区在线视频| 欧美富婆性猛交| 波多野结衣不卡视频| 成人爽a毛片免费啪啪红桃视频| 欧美精品高清视频| 中文av一区二区三区| www.国产精品| 欧美精品三级在线观看| www.com久久久| 国产一区二区视频在线看| 欧美日本韩国一区| 国产亚洲视频一区| 激情综合五月| 精品久久人人做人人爽| 中文字幕乱视频| 欧美黑人做爰爽爽爽| 在线观看www91| 欧美日韩在线不卡视频| 神马久久资源| 亚洲一二三四区不卡| 精品一区二区三区无码视频| 变态调教一区二区三区| 欧美日韩国产精品一区二区三区四区 | av手机免费看| 成人av在线一区二区三区| 国产精品免费一区二区三区都可以 | 在线播放国产视频| 超碰成人97| 日韩精品999| 熟女少妇内射日韩亚洲| 亚洲一区 二区| 亚洲成人久久电影| 99久久人妻无码中文字幕系列| 西瓜成人精品人成网站| 亚洲性生活视频| 91高清免费观看| 亚洲精华国产欧美| 久久人人爽人人爽爽久久| 国产女人18水真多毛片18精品| 欧美亚洲不卡| 日本精品一区二区三区在线| 一级做a爱片性色毛片| 国产一区二区三区久久悠悠色av | 欧美人体一区二区三区| 欧美日韩一区二区三区免费看| 亚洲高清视频免费| 欧美亚洲色图校园春色| 色阁综合伊人av| 久久视频免费在线观看| 日韩国产精品大片| 91在线免费看片| 天堂网www中文在线| 国产激情视频一区二区三区欧美| 精品国产乱码久久久久| 日本三级在线播放完整版| 亚洲一区二区精品视频| 久久久国产欧美| 红杏视频成人| 精品免费99久久| 中文字幕成人动漫| 狠久久av成人天堂| 国产精品一香蕉国产线看观看| 国模私拍视频在线| 中文字幕一区二区三区精华液| 无码 制服 丝袜 国产 另类| 黑人一区二区三区| 亚洲欧美国产高清va在线播| 欧美人妻精品一区二区免费看| 日本成人在线不卡视频| 久久亚洲一区二区| 激情影院在线| 欧美一级高清片| 制服丨自拍丨欧美丨动漫丨| 亚欧成人精品| 精品国产一区二区三区久久久久久| av免费在线观| 69精品人人人人| 国产午夜精品福利视频| 精品三级av在线导航| 中文字幕在线看视频国产欧美在线看完整 | 国产精品日韩成人| 欧美牲交a欧美牲交aⅴ免费真| 成人爽a毛片| 久久久久久久久久久网站| 国产美女明星三级做爰| 日本一区二区高清| 成年人在线看片| 一区二区三区视频免费观看| 91精品国产高清久久久久久91| 性猛交xxxx乱大交孕妇印度| 亚洲欧美日本在线| 又色又爽又黄视频| 97精品在线| 国产在线日韩在线| 麻豆视频在线免费观看| 欧美美女网站色| 手机在线中文字幕| 精品一区二区国语对白| 福利网在线观看| 日韩精品一区二区三区中文在线| 美女视频久久黄| 国产黄色av片| 亚洲宅男天堂在线观看无病毒| 91精产国品一二三| 亚洲无线一线二线三线区别av| 国产经品一区二区| av第一福利在线导航| 亚洲精品videossex少妇| 影音先锋在线国产| 奇米色777欧美一区二区| 日本视频一区二区不卡| 国产91欧美| 久久久电影免费观看完整版| 99热这里只有精品9| 亚洲一区二区精品视频| 亚洲第一页av| 美女国产一区二区三区| 女同性恋一区二区| 丁香5月婷婷久久| 欧美在线性爱视频 | 久久视频在线直播| 亚洲va欧美va| 色综合视频在线观看| 日本美女xxx| 国产精品一区二区久久不卡 | 草草在线观看| 在线看片第一页欧美| 99视频免费看| 日韩欧美在线视频免费观看| 极品蜜桃臀肥臀-x88av| 国产一区二区免费在线| 久激情内射婷内射蜜桃| 精品久久影院| 成人xxxxx色| 欧美va在线观看| 欧美丰满少妇xxxxx| 国产小视频免费在线观看| 亚洲一区二区三区四区中文字幕| 国产肉体xxxx裸体784大胆| 日韩电影在线免费看| 国产人妻互换一区二区| 婷婷综合电影| 91九色露脸| 久久uomeier| 免费av一区二区| 久久这里精品| 日韩久久久精品| 波多野结衣一区二区在线| 悠悠色在线精品| 中文字幕伦理片| 成人性视频免费网站| 乌克兰美女av| 国产欧美在线| 成人一区二区av| 成人在线日韩| 日本中文字幕不卡免费| 日本性爱视频在线观看| 中文字幕久精品免费视频| 全国男人的天堂网| 制服丝袜激情欧洲亚洲| 亚洲毛片一区二区三区| 亚洲午夜电影在线观看| 精品亚洲乱码一区二区| 久久久国际精品| 蜜桃色一区二区三区| 美女性感视频久久| 成年人视频网站免费观看| 精品91视频| 天天做天天爱天天高潮| 日韩一区欧美| 日本一区二区三区视频在线播放| 美女视频亚洲色图| 99久久精品久久久久久ai换脸| 男女啪啪999亚洲精品| 国产精品成人一区二区三区吃奶| 成年人在线观看网站| 亚洲国产天堂久久国产91 | 国产真实精品久久二三区| 成人性做爰aaa片免费看不忠| 亚洲视频1区| 夜夜添无码一区二区三区| 欧美日韩精选| 成人午夜视频免费观看| 欧美国产另类| 欧美日韩午夜爽爽| 欧美 日韩 国产一区二区在线视频| 亚洲午夜精品福利| 精品盗摄女厕tp美女嘘嘘| 欧美一区二区高清在线观看| 亚洲精品456| 日本一区不卡| 日韩免费久久| 国产91av视频在线观看| 亚洲精品国产首次亮相| 最新视频 - x88av| 香蕉综合视频| a级片一区二区| 亚洲视频综合| 131美女爱做视频| 亚洲一卡久久| 亚洲视频在线观看一区二区三区| 日本一区中文字幕| 五月天中文字幕在线| 国产综合色视频| 丰满人妻一区二区三区大胸 | 国产精品污www一区二区三区| 91精品国产自产精品男人的天堂| 韩国一区二区三区美女美女秀| 久久99国产精品久久99大师| 免费国产一区| 日韩av久操| wwwwww欧美| 亚洲欧美日韩国产一区| www.激情小说.com| 国产在线精品不卡| 欧美日韩一区二区三区四区五区六区| 99精品视频中文字幕| 亚洲av无码一区二区三区人 | 国产在线成人精品午夜| 五月天激情小说综合| 无码人妻精品一区二区50| 欧美日韩一区二区在线观看视频| 一级做a爱片久久毛片| 日韩精品一区二区三区四区视频| 神马午夜一区二区| 一区二区三区久久精品| 成人在线免费看片| 91国内在线视频| 免费在线成人激情电影| 亚洲va久久久噜噜噜| 日本成人中文| 一区二区日本伦理| 在线精品在线| 污视频网站观看| 成人激情小说网站| 免费人成又黄又爽又色| 一区二区三区影院| 99re国产在线| 日韩欧美黄色影院| 国产福利小视频在线观看| 欧美成人精品在线观看| 色香欲www7777综合网| 91嫩草在线| 欧美日韩在线网站| 黄色av网址在线播放| 寂寞少妇一区二区三区| 极品粉嫩小仙女高潮喷水久久| 国产精品国模大尺度视频| 一区二区三区视频免费看| 欧美精品国产精品| 精品无人乱码| 国内精品400部情侣激情| 日本国产亚洲| 欧美尤物一区| 亚洲激情视频| 九色91porny| 国产精品久久久久影院色老大| 日本熟妇一区二区| 欧美丰满高潮xxxx喷水动漫| 麻豆av电影在线观看| 久久免费视频网| 精品国产亚洲日本| 亚洲视频在线二区| 日韩二区三区在线观看| 亚洲精品乱码久久久久久不卡| 亚洲精品一二三区| 在线播放一级片| 亚洲无线码在线一区观看| 精品极品在线| 国产伦精品一区二区三区视频免费| 久久一区二区中文字幕| 成人在线免费播放视频| 92精品国产成人观看免费| 久草国产在线视频| 337p亚洲精品色噜噜| 午夜在线小视频| 国产精品国模在线| 曰本一区二区三区视频| 六月丁香婷婷激情| 不卡的av中国片| 精品一区二区三区人妻| 香蕉成人伊视频在线观看| 日韩xxxxxxxxx| 日韩一区二区电影| 欧美三级电影一区二区三区| 国产精品福利网| 精品日本12videosex| 三级4级全黄60分钟| 91蜜桃网址入口| 久久艹免费视频| 亚洲美女精品成人在线视频| 在线免费日韩片| 欧美性大战久久久久| 欧美激情欧美| 午夜精品免费看| 国产精品国产a| 97av免费视频| 欧美精品在线网站| 中文字幕日韩高清在线| 国产精品69久久久| caoporen国产精品视频| 西西44rtwww国产精品| 日韩精品在线观看一区| 精品国产第一福利网站| 亚欧洲精品在线视频免费观看| 免费在线观看日韩欧美| 国产小视频你懂的| 日韩一级完整毛片| 蜜乳av一区| 久久久精品动漫| 日韩和欧美一区二区三区| 国产黄色录像视频| 日韩你懂的电影在线观看| 九色91在线| 欧美激情www| 麻豆一区二区三| 国产精品白嫩白嫩大学美女| 精品女同一区二区| 婷婷综合六月| 一区二区三区的久久的视频| 丁香天五香天堂综合| 日日噜噜噜噜人人爽亚洲精品| 欲色天天网综合久久| 久久av偷拍| 日本一区二区黄色| 亚洲视频一二区| 天天干天天色天天| 国产精品免费视频xxxx| 红桃视频国产精品| 色婷婷在线影院| 日韩一区二区电影在线| 国产伦精品一区二区三区视频金莲| 杨幂一区欧美专区| 成人免费高清视频在线观看| 无码人妻aⅴ一区二区三区有奶水| 久久久成人精品视频| 日韩黄色网络| 国内av一区二区| 岛国精品视频在线播放| 久操免费在线| 欧美一区二区视频17c| 国产精品123区| 蜜臀99久久精品久久久久小说 |