偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

緩存系列:緩存一致性問(wèn)題的解決思路

開(kāi)發(fā) 新聞
今天我們來(lái)聊聊緩存一致性問(wèn)題,對(duì)于這個(gè)問(wèn)題,不管在工作中還是面試中,都是一個(gè)非常常見(jiàn)的問(wèn)題。

大家好,我是李哥。

上次我們討論了在分布式系統(tǒng)下的緩存架構(gòu)體系,從瀏覽器緩存到客戶端緩存,再到CDN緩存,再到反向代理緩存,再到本地緩存,再到分布式緩存。整個(gè)鏈路中有非常多的緩存。

在整個(gè)緩存鏈路,存在各種各樣的問(wèn)題,常見(jiàn)的問(wèn)題有緩存穿透、緩存擊穿、緩存雪崩、緩存數(shù)據(jù)一致性問(wèn)題等。不常見(jiàn)的問(wèn)題有緩存傾斜、緩存阻塞、緩存慢查詢、緩存主從一致性問(wèn)題、緩存高可用、緩存故障發(fā)現(xiàn)與故障恢復(fù)、集群擴(kuò)容收縮、大Key熱Key等等。

今天我們來(lái)聊聊緩存一致性問(wèn)題,對(duì)于這個(gè)問(wèn)題,不管在工作中還是面試中,都是一個(gè)非常常見(jiàn)的問(wèn)題。

今天我們的主題是: 緩存一致性問(wèn)題

老規(guī)矩,上大綱:

圖片

1、緩存一致性問(wèn)題是什么

我們知道,緩存的工作原理是先從緩存中獲取數(shù)據(jù),如果有數(shù)據(jù)則直接返回給用戶,如果沒(méi)有數(shù)據(jù)則從慢速設(shè)備上讀取實(shí)際數(shù)據(jù)并且將數(shù)據(jù)放入緩存。就像這樣:

圖片

但是,這樣的架構(gòu)是存在問(wèn)題的, 因?yàn)閿?shù)據(jù)庫(kù)與緩存是不同的組件,操作必須有先后順序,無(wú)法像數(shù)據(jù)庫(kù)的事務(wù)一樣滿足ACID的特性,所以就會(huì)出現(xiàn)數(shù)據(jù)在緩存中與在數(shù)據(jù)庫(kù)中不一致的問(wèn)題 。

緩存一致性問(wèn)題的表現(xiàn):同一份數(shù)據(jù),緩存中的數(shù)據(jù)與數(shù)據(jù)庫(kù)中的數(shù)據(jù)不一致,那么上升到業(yè)務(wù)層面就有著千奇百怪的現(xiàn)象了,比如每次讀都是讀的老數(shù)據(jù),或者每次讀是一份過(guò)時(shí)的數(shù)據(jù)等。

2、解決方案

對(duì)于寫入操作:

  • 只寫DB,不寫Cache,依賴下次查詢
  • 先寫DB,(同步/異步)再寫Cache
  • 先寫Cache,再寫DB

對(duì)于更新操作:

  • 先更新DB,再刪除Cache
  • 先刪除Cache,再更新DB
  • 先刪除Cache,再更新DB,再刪除Cache

2.1、只寫DB,不寫Cache,依賴下次查詢

這種是我們常見(jiàn)的設(shè)計(jì)方案,這種方案只寫數(shù)據(jù)庫(kù)不寫緩存,依賴下一次請(qǐng)求從數(shù)據(jù)庫(kù)取出數(shù)據(jù)再放入緩存。細(xì)心的讀者已經(jīng)發(fā)現(xiàn)了,這種設(shè)計(jì)有可能引發(fā)新的問(wèn)題:緩存擊穿(復(fù)習(xí)緩存擊穿:DB有數(shù)據(jù),Cache無(wú)數(shù)據(jù),瞬間流量將DB擊穿)。

這種可能性是存在的,但是可能性比較小,因?yàn)榫彺鎿舸┑那疤釛l件是大量請(qǐng)求透過(guò)緩存打入數(shù)據(jù)庫(kù)層,但是因?yàn)槲覀冇懻摫敬涡?biāo)題的前提條件是新寫入,一般不會(huì)有很大的瞬間流量進(jìn)來(lái)。就算有,那也不屬于本文緩存一致性問(wèn)題的討論范圍了。

圖片

2.2、先寫數(shù)據(jù)庫(kù),再寫緩存

這種也是我們常見(jiàn)的設(shè)計(jì)方案,先寫數(shù)據(jù)庫(kù),再寫緩存,上面的圖也有體現(xiàn)這一點(diǎn)。

圖片

所以在這種場(chǎng)景下,線程1再去讀數(shù)據(jù)的時(shí)候,讀數(shù)據(jù)則優(yōu)先走緩存,緩存此時(shí)值為1,所以讀到的值是1,此時(shí)線程1懵逼了啊......我剛才不是更新成2了嗎?

大家還記得之前的一篇文章《 緩存系列:緩存擊穿的解決思路 》,在面臨緩存穿透的時(shí)候,我們其中一個(gè)解決方案是:查詢數(shù)據(jù)庫(kù)如果沒(méi)有數(shù)據(jù),則約定一個(gè)空數(shù)據(jù)格式放入緩存中,當(dāng)再次查詢的時(shí)候,先查詢緩存,發(fā)現(xiàn)是一個(gè)空數(shù)據(jù)格式,則直接返回空,避免數(shù)據(jù)庫(kù)被瞬間流量擊垮。在這個(gè)方案下,還有第二個(gè)步驟,當(dāng)數(shù)據(jù)保存后,需要主動(dòng)將數(shù)據(jù)放入緩存,以便下次能夠查詢。

所以如果你的系統(tǒng)中如果有做緩存穿透的防護(hù),有可能你寫完數(shù)據(jù)庫(kù)后還需要記得寫緩存。

2.3、先寫緩存,再寫數(shù)據(jù)庫(kù)

顧名思義,就是一個(gè)寫操作,先寫緩存,成功后,再寫數(shù)據(jù)庫(kù)。

那么,如果寫數(shù)據(jù)庫(kù)失敗呢?

如果寫失敗了,在下次讀的時(shí)候那么就會(huì)讀取到臟數(shù)據(jù)的情況。

如果寫數(shù)據(jù)庫(kù)失敗,有兩種方案

  1. 刪除緩存
  2. 異步任務(wù)繼續(xù)寫數(shù)據(jù)庫(kù)

這兩個(gè)方案都有問(wèn)題!

下面我們挨個(gè)分析。

刪除緩存。如果刪除緩存失敗呢?再用異步任務(wù)重試刪除?那你是否有考慮重試的時(shí)候這種短暫不一致的情況?還是說(shuō)接受這種數(shù)據(jù)不一致的情況?系統(tǒng)復(fù)雜度被你提高了多少?

異步任務(wù)繼續(xù)寫數(shù)據(jù)庫(kù)。異步任務(wù)如果寫失敗呢?重試?重試也一直失敗呢?重試任務(wù)落庫(kù)+定時(shí)任務(wù)兜底?可以,那么,短暫的數(shù)據(jù)不一致是否接受?系統(tǒng)復(fù)雜度被你提高了多少?

所以,這種先寫緩存再寫數(shù)據(jù)庫(kù)的方案一般不會(huì)正式使用,一旦出問(wèn)題,很難保證數(shù)據(jù)的最終一致性。

接下來(lái)我們討論一下更新數(shù)據(jù)的情況。

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

這種情況下,你可能想說(shuō)這是你們現(xiàn)在正在使用的技術(shù)方案,但是我想說(shuō)是這個(gè)方案是存在問(wèn)題的,別慌反駁,大家看看這張圖:

首先,這種技術(shù)方案,確實(shí)是我們?cè)谌粘i_(kāi)發(fā)中是最常見(jiàn)的,但是作為開(kāi)發(fā)的我們,也應(yīng)該明白它存在什么問(wèn)題,以及能夠有哪些應(yīng)對(duì)措施,下面談?wù)勎覀€(gè)人對(duì)這個(gè)解決方案的一些改進(jìn)。

  1. 延遲刪除緩存。
  2. 先刪除緩存,再更新數(shù)據(jù)庫(kù)。
  3. 延遲雙刪策略。
  4. 定時(shí)任務(wù)增量/全量更新緩存數(shù)據(jù)。
  5. 監(jiān)聽(tīng)數(shù)據(jù)庫(kù)binlog增量數(shù)據(jù)更新緩存。

方案一:延遲刪除緩存。這種改進(jìn)方案的優(yōu)點(diǎn)是能有效的防止數(shù)據(jù)不一致,但不能夠完全防止。為什么說(shuō)不能夠完全防止呢?因?yàn)椴樵償?shù)據(jù)的那個(gè)線程有可能也延遲了一定時(shí)間才去更新緩存。這個(gè)改進(jìn)方案的缺點(diǎn)是無(wú)法嚴(yán)格的控制時(shí)間,這個(gè)時(shí)間需要開(kāi)發(fā)人員根據(jù)經(jīng)驗(yàn)給出,第二個(gè)缺點(diǎn)是延遲行為有可能讓系統(tǒng)引入一些新的依賴,你可能想說(shuō)是否可以用jdk自帶的延遲隊(duì)列呢?可以,但是如果延遲期間,服務(wù)重啟了,怎么處理?第三個(gè)缺點(diǎn)是可能導(dǎo)致系統(tǒng)的復(fù)雜度提高、維護(hù)成本提高、可讀性降低。

方案二:先刪除緩存,再更新數(shù)據(jù)庫(kù)。這個(gè)方案我們下面單獨(dú)細(xì)說(shuō),這里咱不介紹。

方案三:延遲雙刪策略。這個(gè)方案我們下面單獨(dú)細(xì)說(shuō),這里咱不介紹。

方案四:定時(shí)任務(wù)增量/全量更新緩存數(shù)據(jù)。這種解題方式是最直接最暴力的,它的優(yōu)點(diǎn)是能夠保證數(shù)據(jù)的最終一致性。它的缺點(diǎn)有:可能需要引入分布式調(diào)度任務(wù)(如果不引入則又存在多實(shí)例同時(shí)更新的情況,純屬浪費(fèi)資源,或者加分布式鎖)、如果是增量同步的話則需要有一種方式方法區(qū)分出什么數(shù)據(jù)才是增量數(shù)據(jù),這種方式可能有業(yè)務(wù)侵入和性能影響、如果是全量同步的話數(shù)據(jù)量太多又太耗時(shí),嚴(yán)重的話可能導(dǎo)致任務(wù)阻塞以及加重?cái)?shù)據(jù)不一致的問(wèn)題。經(jīng)過(guò)分析,優(yōu)點(diǎn)很明顯,一般情況下,異步主動(dòng)的對(duì)緩存數(shù)據(jù)更新是一種不可采取的方式。但是也會(huì)有一些業(yè)務(wù)場(chǎng)景,數(shù)據(jù)變更不太頻繁,但是訪問(wèn)非常頻繁,并且更新數(shù)據(jù)更新時(shí)間已經(jīng)同步更新緩存了,再使用這種異步將DB數(shù)據(jù)載入緩存作為兜底的策略是可行的。

方案五:監(jiān)聽(tīng)數(shù)據(jù)庫(kù)binlog增量數(shù)據(jù)更新緩存。

這種方式讓開(kāi)發(fā)不再關(guān)注緩存層,專注于業(yè)務(wù)開(kāi)發(fā),只關(guān)注于數(shù)據(jù)庫(kù),而不用關(guān)心緩存。

可以看到這種方案對(duì)研發(fā)人員來(lái)說(shuō)比較輕量,不用關(guān)心緩存層面,而且這個(gè)方案雖然比較重,但是卻容易形成統(tǒng)一的解決方案。

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

這種方式也比較容易理解,先刪除緩存數(shù)據(jù),再更新DB的數(shù)據(jù),如果刪除緩存失敗了,直接返回失?。蝗绻翫B失敗了,影響的也只是刪除緩存而已,下次查詢的時(shí)候重新種一次即可。

那如果,會(huì)不會(huì)因?yàn)閯h除了緩存的數(shù)據(jù),從而導(dǎo)致DB被擊穿呢?這種可能性是存在的,但是可能性比較小。

再說(shuō)了,這種方案真的可以解決問(wèn)題嗎?如果在刪除緩存后,馬上有新線程查詢緩存,新線程發(fā)現(xiàn)緩存不存在(剛被刪),新線程查詢數(shù)據(jù)庫(kù)后將數(shù)據(jù)放于緩存,老線程刪除數(shù)據(jù)庫(kù)成功。此時(shí)數(shù)據(jù)庫(kù)無(wú)數(shù)據(jù),緩存有數(shù)據(jù)。

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

基于2.5,在這個(gè)基礎(chǔ)上可以做出一些改進(jìn),那就是延遲雙刪。

延遲雙刪的流程:刪除緩存->刪除DB->延遲一段時(shí)間再刪除緩存。

延遲雙刪能解決大部分的問(wèn)題,但是在極端情況下,還是會(huì)出現(xiàn)問(wèn)題,造成數(shù)據(jù)不一致。

這里存在一個(gè)問(wèn)題,延遲一段時(shí)間,是延遲多久?1s?3s?這是一個(gè)經(jīng)驗(yàn)值,一般情況是1s~2s。具體取值根據(jù)監(jiān)控實(shí)際情況而定。那既然是估計(jì)值,那么就一定存在誤差,所以必然極端情況下的數(shù)據(jù)不一致問(wèn)題。

解決這個(gè)問(wèn)題的方法之前也說(shuō)了,監(jiān)聽(tīng)數(shù)據(jù)庫(kù)binlog增量數(shù)據(jù)更新緩存,或者還可以使用異步消息等。

3、總結(jié)

在實(shí)際的工作中,或者在面試中,如果有人問(wèn)你各種沒(méi)有場(chǎng)景化的純粹的技術(shù)問(wèn)題,比如說(shuō)有人看了上面的種種方案還是會(huì)提出疑問(wèn),你的這些方案仍然存在數(shù)據(jù)不一致的問(wèn)題啊,那怎么解決呢?

技術(shù)是為了業(yè)務(wù)服務(wù)的,所以,在所有不同的業(yè)務(wù)場(chǎng)景下,對(duì)于技術(shù)的選擇,和方案的設(shè)計(jì)都是不同的。我們需要反問(wèn)他,具體的業(yè)務(wù)場(chǎng)景是什么?我們需要根據(jù)具體的業(yè)務(wù)場(chǎng)景來(lái)選擇最合適的技術(shù)方案。

我們要明確的是:一個(gè)技術(shù)方案不可能cover住所有的場(chǎng)景,脫離業(yè)務(wù)的技術(shù)都是刷流氓。

責(zé)任編輯:張燕妮 來(lái)源: 李哥技術(shù)
相關(guān)推薦

2024-04-11 13:45:14

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

2024-11-14 07:10:00

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2025-06-16 02:11:00

2023-04-13 08:15:47

Redis緩存一致性

2020-09-04 06:32:08

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

2022-12-14 08:23:30

2020-06-01 22:09:48

緩存緩存同步緩存誤用

2021-09-08 11:03:13

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

2016-11-29 09:00:19

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

2022-08-28 16:31:11

緩存雪崩

2024-11-07 22:57:30

2019-03-27 13:56:39

緩存雪崩穿透

2020-05-12 10:43:22

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

2023-05-09 10:59:33

緩存技術(shù)派MySQL

2020-09-22 08:07:50

緩存數(shù)據(jù)一致性

2025-08-08 07:09:58

2022-09-16 09:46:42

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

2022-10-08 00:00:09

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

2022-08-11 07:55:05

數(shù)據(jù)庫(kù)Mysql
點(diǎn)贊
收藏

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