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

緩存同步、如何保證緩存一致性、緩存誤用

存儲(chǔ) 存儲(chǔ)軟件
緩存,是互聯(lián)網(wǎng)分層架構(gòu)中,非常重要的一個(gè)部分,通常用它來(lái)降低數(shù)據(jù)庫(kù)壓力,提升系統(tǒng)整體性能,縮短訪問(wèn)時(shí)間。

 [[328476]]

緩存誤用

緩存,是互聯(lián)網(wǎng)分層架構(gòu)中,非常重要的一個(gè)部分,通常用它來(lái)降低數(shù)據(jù)庫(kù)壓力,提升系統(tǒng)整體性能,縮短訪問(wèn)時(shí)間。

有架構(gòu)師說(shuō)“緩存是萬(wàn)金油,哪里有問(wèn)題,加個(gè)緩存,就能優(yōu)化”,緩存的濫用,可能會(huì)導(dǎo)致一些錯(cuò)誤用法。

緩存,你真的用對(duì)了么?

誤用一:把緩存作為服務(wù)與服務(wù)之間傳遞數(shù)據(jù)的媒介

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:

服務(wù)1和服務(wù)2約定好key和value,通過(guò)緩存?zhèn)鬟f數(shù)據(jù)

服務(wù)1將數(shù)據(jù)寫(xiě)入緩存,服務(wù)2從緩存讀取數(shù)據(jù),達(dá)到兩個(gè)服務(wù)通信的目的

該方案存在的問(wèn)題是:

1、數(shù)據(jù)管道,數(shù)據(jù)通知場(chǎng)景,MQ更加適合

(1)MQ是互聯(lián)網(wǎng)常見(jiàn)的邏輯解耦,物理解耦組件,支持1對(duì)1,1對(duì)多各種模式,非常成熟的數(shù)據(jù)通道,而cache反而會(huì)將service-A/B/C/D耦合在一起,大家要彼此協(xié)同約定key的格式,ip地址等

(2)MQ能夠支持push,而cache只能拉取,不實(shí)時(shí),有時(shí)延

(3)MQ天然支持集群,支持高可用,而cache未必

(4)MQ能支持?jǐn)?shù)據(jù)落地,cache具備將數(shù)據(jù)存在內(nèi)存里,具有“易失”性,當(dāng)然,有些cache支持落地,但互聯(lián)網(wǎng)技術(shù)選型的原則是,讓專業(yè)的軟件干專業(yè)的事情:nginx做反向代理,db做固化,cache做緩存,mq做通道

2、多個(gè)服務(wù)關(guān)聯(lián)同一個(gè)緩存實(shí)例,會(huì)導(dǎo)致服務(wù)耦合

(1)大家要彼此協(xié)同約定key的格式,ip地址等,耦合

(2)約定好同一個(gè)key,可能會(huì)產(chǎn)生數(shù)據(jù)覆蓋,導(dǎo)致數(shù)據(jù)不一致

(3)不同服務(wù)業(yè)務(wù)模式,數(shù)據(jù)量,并發(fā)量不一樣,會(huì)因?yàn)橐粋€(gè)cache相互影響,例如service-A數(shù)據(jù)量大,占用了cache的絕大部分內(nèi)存,會(huì)導(dǎo)致service-B的熱數(shù)據(jù)全部被擠出cache,導(dǎo)致cache失效;又例如service-A并發(fā)量高,占用了cache的絕大部分連接,會(huì)導(dǎo)致service-B拿不到cache的連接,從而服務(wù)異常

誤用二:使用緩存未考慮雪崩

 

緩存同步、如何保證緩存一致性、緩存誤用

 

常規(guī)的緩存玩法,如上圖:

服務(wù)先讀緩存,緩存命中則返回

緩存不命中,再讀數(shù)據(jù)庫(kù)

什么時(shí)候會(huì)產(chǎn)生雪崩?

答:如果緩存掛掉,所有的請(qǐng)求會(huì)壓到數(shù)據(jù)庫(kù),如果未提前做容量預(yù)估,可能會(huì)把數(shù)據(jù)庫(kù)壓垮(在緩存恢復(fù)之前,數(shù)據(jù)庫(kù)可能一直都起不來(lái)),導(dǎo)致系統(tǒng)整體不可服務(wù)。

如何應(yīng)對(duì)潛在的雪崩?

答:提前做容量預(yù)估,如果緩存掛掉,數(shù)據(jù)庫(kù)仍能扛住,才能執(zhí)行上述方案。

否則,就要進(jìn)一步設(shè)計(jì)。

常見(jiàn)方案一:高可用緩存

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:使用高可用緩存集群,一個(gè)緩存實(shí)例掛掉后,能夠自動(dòng)做故障轉(zhuǎn)移。

常見(jiàn)方案二:緩存水平切分

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:使用緩存水平切分(推薦使用一致性哈希算法進(jìn)行切分),一個(gè)緩存實(shí)例掛掉后,不至于所有的流量都?jí)旱綌?shù)據(jù)庫(kù)上。

誤用三:調(diào)用方緩存數(shù)據(jù)

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:

服務(wù)提供方緩存,向調(diào)用方屏蔽數(shù)據(jù)獲取的復(fù)雜性(這個(gè)沒(méi)問(wèn)題)

服務(wù)調(diào)用方,也緩存一份數(shù)據(jù),先讀自己的緩存,再?zèng)Q定是否調(diào)用服務(wù)(這個(gè)有問(wèn)題)

該方案存在的問(wèn)題是:

1、調(diào)用方需要關(guān)注數(shù)據(jù)獲取的復(fù)雜性(耦合問(wèn)題)

2、更嚴(yán)重的,服務(wù)修改db里的數(shù)據(jù),淘汰了服務(wù)cache之后,難以通知調(diào)用方淘汰其cache里的數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)不一致(帶入一致性問(wèn)題)

3、有人說(shuō),服務(wù)可以通過(guò)MQ通知調(diào)用方淘汰數(shù)據(jù),額,難道下游的服務(wù)要依賴上游的調(diào)用方,分層架構(gòu)設(shè)計(jì)不是這么玩的(反向依賴問(wèn)題)

誤用四:多服務(wù)共用緩存實(shí)例

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:服務(wù)A和服務(wù)B共用一個(gè)緩存實(shí)例(不是通過(guò)這個(gè)緩存實(shí)例交互數(shù)據(jù))

該方案存在的問(wèn)題是:

1、可能導(dǎo)致key沖突,彼此沖掉對(duì)方的數(shù)據(jù)

畫(huà)外音:可能需要服務(wù)A和服務(wù)B提前約定好了key,以確保不沖突,常見(jiàn)的約定方式是使用namespace:key的方式來(lái)做key。

2、不同服務(wù)對(duì)應(yīng)的數(shù)據(jù)量,吞吐量不一樣,共用一個(gè)實(shí)例容易導(dǎo)致一個(gè)服務(wù)把另一個(gè)服務(wù)的熱數(shù)據(jù)擠出去

3、共用一個(gè)實(shí)例,會(huì)導(dǎo)致服務(wù)之間的耦合,與微服務(wù)架構(gòu)的“數(shù)據(jù)庫(kù),緩存私有”的設(shè)計(jì)原則是相悖的

建議的玩法是

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:各個(gè)服務(wù)私有化自己的數(shù)據(jù)存儲(chǔ),對(duì)上游屏蔽底層的復(fù)雜性。

總結(jié)

1、服務(wù)與服務(wù)之間不要通過(guò)緩存?zhèn)鬟f數(shù)據(jù)

2、如果緩存掛掉,可能導(dǎo)致雪崩,此時(shí)要做高可用緩存,或者水平切分

3、調(diào)用方不宜再單獨(dú)使用緩存存儲(chǔ)服務(wù)底層的數(shù)據(jù),容易出現(xiàn)數(shù)據(jù)不一致,以及反向依賴

4、不同服務(wù),緩存實(shí)例要做垂直拆分

緩存,究竟是淘汰,還是修改?

KV緩存都緩存了一些什么數(shù)據(jù)?

答:

(1)樸素類型的數(shù)據(jù),例如:int

(2)序列化后的對(duì)象,例如:User實(shí)體,本質(zhì)是binary

(3)文本數(shù)據(jù),例如:json或者h(yuǎn)tml

(4)...

淘汰緩存中的這些數(shù)據(jù),修改緩存中的這些數(shù)據(jù),有什么差別?

答:

(1)淘汰某個(gè)key,操作簡(jiǎn)單,直接將key置為無(wú)效,但下一次該key的訪問(wèn)會(huì)cache miss

(2)修改某個(gè)key的內(nèi)容,邏輯相對(duì)復(fù)雜,但下一次該key的訪問(wèn)仍會(huì)cache hit

可以看到,差異僅僅在于一次cache miss。

緩存中的value數(shù)據(jù)一般是怎么修改的?

答:

(1)樸素類型的數(shù)據(jù),直接set修改后的值即可

(2)序列化后的對(duì)象:一般需要先get數(shù)據(jù),反序列化成對(duì)象,修改其中的成員,再序列化為binary,再set數(shù)據(jù)

(3)json或者h(yuǎn)tml數(shù)據(jù):一般也需要先get文本,parse成dom樹(shù)對(duì)象,修改相關(guān)元素,序列化為文本,再set數(shù)據(jù)

結(jié)論:對(duì)于對(duì)象類型,或者文本類型,修改緩存value的成本較高,一般選擇直接淘汰緩存。

問(wèn):對(duì)于樸素類型的數(shù)據(jù),究竟應(yīng)該修改緩存,還是淘汰緩存?

答:仍然視情況而定。

案例1:

假設(shè),緩存里存了某一個(gè)用戶uid=123的余額是money=100元,業(yè)務(wù)場(chǎng)景是,購(gòu)買(mǎi)了一個(gè)商品pid=456。

分析:如果修改緩存,可能需要:

(1)去db查詢pid的價(jià)格是50元

(2)去db查詢活動(dòng)的折扣是8折(商品實(shí)際價(jià)格是40元)

(3)去db查詢用戶的優(yōu)惠券是10元(用戶實(shí)際要支付30元)

(4)從cache查詢get用戶的余額是100元

(5)計(jì)算出剩余余額是100 - 30 = 70

(6)到cache設(shè)置set用戶的余額是70

為了避免一次cache miss,需要額外增加若干次db與cache的交互,得不償失。

結(jié)論:此時(shí),應(yīng)該淘汰緩存,而不是修改緩存。

案例2:

假設(shè),緩存里存了某一個(gè)用戶uid=123的余額是money=100元,業(yè)務(wù)場(chǎng)景是,需要扣減30元。

分析:如果修改緩存,需要:

(1)從cache查詢get用戶的余額是100元

(2)計(jì)算出剩余余額是100 - 30 = 70

(3)到cache設(shè)置set用戶的余額是70

為了避免一次cache miss,需要額外增加若干次cache的交互,以及業(yè)務(wù)的計(jì)算,得不償失。

結(jié)論:此時(shí),應(yīng)該淘汰緩存,而不是修改緩存。

案例3:

假設(shè),緩存里存了某一個(gè)用戶uid=123的余額是money=100元,業(yè)務(wù)場(chǎng)景是,余額要變?yōu)?0元。

分析:如果修改緩存,需要:

修改緩存成本很低。

結(jié)論:此時(shí),可以選擇修改緩存。當(dāng)然,如果選擇淘汰緩存,只會(huì)額外增加一次cache miss,成本也不高。

總結(jié):

大部分情況,修改value成本會(huì)高于“增加一次cache miss”,因此應(yīng)該淘汰緩存

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

這里分了兩種觀點(diǎn),Cache Aside Pattern的觀點(diǎn)、沈老師的觀點(diǎn)。下面兩種觀點(diǎn)分析一下。

Cache Aside Pattern

什么是“Cache Aside Pattern”?

對(duì)于讀請(qǐng)求

 

緩存同步、如何保證緩存一致性、緩存誤用

 

(1)先從cache中嘗試get數(shù)據(jù),結(jié)果miss了

(2)再?gòu)膁b中讀取數(shù)據(jù),從庫(kù),讀寫(xiě)分離

(3)最后把數(shù)據(jù)set回cache,方便下次讀命中

對(duì)于寫(xiě)請(qǐng)求

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖:

(2)緩存,采用delete淘汰,而不是set更新

Cache Aside Pattern為什么建議淘汰緩存,而不是更新緩存?

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖所示,如果采用set緩存。

在1和2兩個(gè)并發(fā)寫(xiě)發(fā)生時(shí),由于無(wú)法保證時(shí)序,此時(shí)不管先操作緩存還是先操作數(shù)據(jù)庫(kù),都可能出現(xiàn):

(2)請(qǐng)求2先set了緩存,請(qǐng)求1后set了緩存

Cache Aside Pattern為什么建議先操作數(shù)據(jù)庫(kù),再操作緩存?

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖所示,如果先操作緩存。

在1和2并發(fā)讀寫(xiě)發(fā)生時(shí),由于無(wú)法保證時(shí)序,可能出現(xiàn):

(2)寫(xiě)請(qǐng)求操作了數(shù)據(jù)庫(kù)(主從同步?jīng)]有完成)

(3)讀請(qǐng)求讀了緩存(cache miss)

(4)讀請(qǐng)求讀了從庫(kù)(讀了一個(gè)舊數(shù)據(jù))

(5)讀請(qǐng)求set回緩存(set了一個(gè)舊數(shù)據(jù))

(6)數(shù)據(jù)庫(kù)主從同步完成

所以,Cache Aside Pattern建議,先操作數(shù)據(jù)庫(kù),再操作緩存。

Cache Aside Pattern方案存在什么問(wèn)題?

(2)淘汰緩存失敗了

導(dǎo)致,數(shù)據(jù)庫(kù)與緩存的數(shù)據(jù)不一致。

個(gè)人見(jiàn)解:這里個(gè)人覺(jué)得可以使用重試的方法,在淘汰緩存的時(shí)候,如果失敗,則重試一定的次數(shù)。如果失敗一定次數(shù)還不行,那就是其他原因了。比如說(shuō)redis故障、內(nèi)網(wǎng)出了問(wèn)題。

關(guān)于這個(gè)問(wèn)題,沈老師的解決方案是,使用先操作緩存(delete),再操作數(shù)據(jù)庫(kù)。假如刪除緩存成功,更新數(shù)據(jù)庫(kù)失敗了。緩存里沒(méi)有數(shù)據(jù),數(shù)據(jù)庫(kù)里是之前的數(shù)據(jù),數(shù)據(jù)沒(méi)有不一致,對(duì)業(yè)務(wù)無(wú)影響。只是下一次讀取,會(huì)多一次cache miss。這里我覺(jué)得沈老師可能忽略了并發(fā)的問(wèn)題,比如說(shuō)以下情況:

如圖:

 

緩存同步、如何保證緩存一致性、緩存誤用

 

不一致解決場(chǎng)景及解決方案

答:發(fā)生寫(xiě)請(qǐng)求后(不管是先操作DB,還是先淘汰Cache),在主從數(shù)據(jù)庫(kù)同步完成之前,如果有讀請(qǐng)求,都可能發(fā)生讀Cache Miss,讀從庫(kù)把舊數(shù)據(jù)存入緩存的情況。此時(shí)怎么辦呢?

一、數(shù)據(jù)庫(kù)主從不一致

先回顧下,無(wú)緩存時(shí),數(shù)據(jù)庫(kù)主從不一致問(wèn)題。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,發(fā)生的場(chǎng)景是,寫(xiě)后立刻讀:

(1)主庫(kù)一個(gè)寫(xiě)請(qǐng)求(主從沒(méi)同步完成)

(2)從庫(kù)接著一個(gè)讀請(qǐng)求,讀到了舊數(shù)據(jù)

(3)最后,主從同步完成

導(dǎo)致的結(jié)果是:主動(dòng)同步完成之前,會(huì)讀取到舊數(shù)據(jù)。

可以看到,主從不一致的影響時(shí)間很短,在主從同步完成后,就會(huì)讀到新數(shù)據(jù)。

二、緩存與數(shù)據(jù)庫(kù)不一致

再看,引入緩存后,緩存和數(shù)據(jù)庫(kù)不一致問(wèn)題。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,發(fā)生的場(chǎng)景也是,寫(xiě)后立刻讀:

(1+2)先一個(gè)寫(xiě)請(qǐng)求,淘汰緩存,寫(xiě)數(shù)據(jù)庫(kù)

(3+4+5)接著立刻一個(gè)讀請(qǐng)求,讀緩存,cache miss,讀從庫(kù),寫(xiě)緩存放入數(shù)據(jù),以便后續(xù)的讀能夠cache hit(主從同步?jīng)]有完成,緩存中放入了舊數(shù)據(jù))

(6)最后,主從同步完成

導(dǎo)致的結(jié)果是:舊數(shù)據(jù)放入緩存,即使主從同步完成,后續(xù)仍然會(huì)從緩存一直讀取到舊數(shù)據(jù)。

可以看到,加入緩存后,導(dǎo)致的不一致影響時(shí)間會(huì)很長(zhǎng),并且最終也不會(huì)達(dá)到一致。

三、問(wèn)題分析

可以看到,這里提到的緩存與數(shù)據(jù)庫(kù)數(shù)據(jù)不一致,根本上是由數(shù)據(jù)庫(kù)主從不一致引起的。當(dāng)主庫(kù)上發(fā)生寫(xiě)操作之后,從庫(kù)binlog同步的時(shí)間間隔內(nèi),讀請(qǐng)求,可能導(dǎo)致有舊數(shù)據(jù)入緩存。

思路:那能不能寫(xiě)操作記錄下來(lái),在主從時(shí)延的時(shí)間段內(nèi),讀取修改過(guò)的數(shù)據(jù)的話,強(qiáng)制讀主,并且更新緩存,這樣子緩存內(nèi)的數(shù)據(jù)就是最新。在主從時(shí)延過(guò)后,這部分?jǐn)?shù)據(jù)繼續(xù)讀從庫(kù),從而繼續(xù)利用從庫(kù)提高讀取能力。

四、不一致解決方案

選擇性讀主

可以利用一個(gè)緩存記錄必須讀主的數(shù)據(jù)。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,當(dāng)寫(xiě)請(qǐng)求發(fā)生時(shí):

(1)寫(xiě)主庫(kù)

(2)將哪個(gè)庫(kù),哪個(gè)表,哪個(gè)主鍵三個(gè)信息拼裝一個(gè)key設(shè)置到cache里,這條記錄的超時(shí)時(shí)間,設(shè)置為“主從同步時(shí)延”

PS:key的格式為“db:table:PK”,假設(shè)主從延時(shí)為1s,這個(gè)key的cache超時(shí)時(shí)間也為1s。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,當(dāng)讀請(qǐng)求發(fā)生時(shí):

這是要讀哪個(gè)庫(kù),哪個(gè)表,哪個(gè)主鍵的數(shù)據(jù)呢,也將這三個(gè)信息拼裝一個(gè)key,到cache里去查詢,如果,

(1)cache里有這個(gè)key,說(shuō)明1s內(nèi)剛發(fā)生過(guò)寫(xiě)請(qǐng)求,數(shù)據(jù)庫(kù)主從同步可能還沒(méi)有完成,此時(shí)就應(yīng)該去主庫(kù)查詢。并且把主庫(kù)的數(shù)據(jù)set到緩存中,防止下一次cahce miss。

(2)cache里沒(méi)有這個(gè)key,說(shuō)明最近沒(méi)有發(fā)生過(guò)寫(xiě)請(qǐng)求,此時(shí)就可以去從庫(kù)查詢

以此,保證讀到的一定不是不一致的臟數(shù)據(jù)。

PS:如果系統(tǒng)可以接收短時(shí)間的不一致,建議建議定時(shí)更新緩存就可以了。避免系統(tǒng)過(guò)于復(fù)雜。

進(jìn)程內(nèi)緩存

除了常見(jiàn)的redis/memcache等進(jìn)程外緩存服務(wù),緩存還有一種常見(jiàn)的玩法,進(jìn)程內(nèi)緩存。

什么是進(jìn)程內(nèi)緩存?

答:將一些數(shù)據(jù)緩存在站點(diǎn),或者服務(wù)的進(jìn)程內(nèi),這就是進(jìn)程內(nèi)緩存。

進(jìn)程內(nèi)緩存的實(shí)現(xiàn)載體,最簡(jiǎn)單的,可以是一個(gè)帶鎖的Map。又或者,可以使用第三方庫(kù),例如leveldb、guave本地緩存

進(jìn)程內(nèi)緩存能存儲(chǔ)啥?

答:redis/memcache等進(jìn)程外緩存服務(wù)能存什么,進(jìn)程內(nèi)緩存就能存什么。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,可以存儲(chǔ)json數(shù)據(jù),可以存儲(chǔ)html頁(yè)面,可以存儲(chǔ)對(duì)象。

進(jìn)程內(nèi)緩存有什么好處?

答:與沒(méi)有緩存相比,進(jìn)程內(nèi)緩存的好處是,數(shù)據(jù)讀取不再需要訪問(wèn)后端,例如數(shù)據(jù)庫(kù)。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,整個(gè)訪問(wèn)流程要經(jīng)過(guò)1,2,3,4四個(gè)步驟。

如果引入進(jìn)程內(nèi)緩存,

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,整個(gè)訪問(wèn)流程只要經(jīng)過(guò)1,2兩個(gè)步驟。

與進(jìn)程外緩存相比(例如redis/memcache),進(jìn)程內(nèi)緩存省去了網(wǎng)絡(luò)開(kāi)銷(xiāo),所以一來(lái)節(jié)省了內(nèi)網(wǎng)帶寬,二來(lái)響應(yīng)時(shí)延會(huì)更低。

進(jìn)程內(nèi)緩存有什么缺點(diǎn)?

答:統(tǒng)一緩存服務(wù)雖然多一次網(wǎng)絡(luò)交互,但仍是統(tǒng)一存儲(chǔ)。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

如上圖,站點(diǎn)和服務(wù)中的多個(gè)節(jié)點(diǎn)訪問(wèn)統(tǒng)一的緩存服務(wù),數(shù)據(jù)統(tǒng)一存儲(chǔ),容易保證數(shù)據(jù)的一致性。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

而進(jìn)程內(nèi)緩存,如上圖,如果數(shù)據(jù)緩存在站點(diǎn)和服務(wù)的多個(gè)節(jié)點(diǎn)內(nèi),數(shù)據(jù)存了多份,一致性比較難保障。

如何保證進(jìn)程內(nèi)緩存的數(shù)據(jù)一致性?

答:保障進(jìn)程內(nèi)緩存一致性,有三種方案。

第一種方案

可以通過(guò)單節(jié)點(diǎn)通知其他節(jié)點(diǎn)。如上圖:寫(xiě)請(qǐng)求發(fā)生在server1,在修改完自己內(nèi)存數(shù)據(jù)與數(shù)據(jù)庫(kù)中的數(shù)據(jù)之后,可以主動(dòng)通知其他server節(jié)點(diǎn),也修改內(nèi)存的數(shù)據(jù)。如下圖:

 

緩存同步、如何保證緩存一致性、緩存誤用

 

這種方案的缺點(diǎn)是:同一功能的一個(gè)集群的多個(gè)節(jié)點(diǎn),相互耦合在一起,特別是節(jié)點(diǎn)較多時(shí),網(wǎng)狀連接關(guān)系極其復(fù)雜。

第二種方案

可以通過(guò)MQ通知其他節(jié)點(diǎn)。如上圖,寫(xiě)請(qǐng)求發(fā)生在server1,在修改完自己內(nèi)存數(shù)據(jù)與數(shù)據(jù)庫(kù)中的數(shù)據(jù)之后,給MQ發(fā)布數(shù)據(jù)變化通知,其他server節(jié)點(diǎn)訂閱MQ消息,也修改內(nèi)存數(shù)據(jù)。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

這種方案雖然解除了節(jié)點(diǎn)之間的耦合,但引入了MQ,使得系統(tǒng)更加復(fù)雜。

前兩種方案,節(jié)點(diǎn)數(shù)量越多,數(shù)據(jù)冗余份數(shù)越多,數(shù)據(jù)同時(shí)更新的原子性越難保證,一致性也就越難保證。

第三種方案

為了避免耦合,降低復(fù)雜性,干脆放棄了“實(shí)時(shí)一致性”,每個(gè)節(jié)點(diǎn)啟動(dòng)一個(gè)timer,定時(shí)從后端拉取最新的數(shù)據(jù),更新內(nèi)存緩存。在有節(jié)點(diǎn)更新后端數(shù)據(jù),而其他節(jié)點(diǎn)通過(guò)timer更新數(shù)據(jù)之間,會(huì)讀到臟數(shù)據(jù)。

 

緩存同步、如何保證緩存一致性、緩存誤用

 

為什么不能頻繁使用進(jìn)程內(nèi)緩存?

答:分層架構(gòu)設(shè)計(jì),有一條準(zhǔn)則:站點(diǎn)層、服務(wù)層要做到無(wú)數(shù)據(jù)無(wú)狀態(tài),這樣才能任意的加節(jié)點(diǎn)水平擴(kuò)展,數(shù)據(jù)和狀態(tài)盡量存儲(chǔ)到后端的數(shù)據(jù)存儲(chǔ)服務(wù),例如數(shù)據(jù)庫(kù)服務(wù)或者緩存服務(wù)。

可以看到,站點(diǎn)與服務(wù)的進(jìn)程內(nèi)緩存,實(shí)際上違背了分層架構(gòu)設(shè)計(jì)的無(wú)狀態(tài)準(zhǔn)則,故一般不推薦使用。

什么時(shí)候可以使用進(jìn)程內(nèi)緩存?

答:以下情況,可以考慮使用進(jìn)程內(nèi)緩存。

情況一

只讀數(shù)據(jù),可以考慮在進(jìn)程啟動(dòng)時(shí)加載到內(nèi)存。

畫(huà)外音:此時(shí)也可以把數(shù)據(jù)加載到redis / memcache,進(jìn)程外緩存服務(wù)也能解決這類問(wèn)題。

情況二

極其高并發(fā)的,如果透?jìng)骱蠖藟毫O大的場(chǎng)景,可以考慮使用進(jìn)程內(nèi)緩存。

例如,秒殺業(yè)務(wù),并發(fā)量極高,需要站點(diǎn)層擋住流量,可以使用內(nèi)存緩存。

情況三

一定程度上允許數(shù)據(jù)不一致業(yè)務(wù)。

例如,有一些計(jì)數(shù)場(chǎng)景,運(yùn)營(yíng)場(chǎng)景,頁(yè)面對(duì)數(shù)據(jù)一致性要求較低,可以考慮使用進(jìn)程內(nèi)頁(yè)面緩存。

再次強(qiáng)調(diào),進(jìn)程內(nèi)緩存的適用場(chǎng)景并不如redis/memcache廣泛,不要為了炫技而使用。更多的時(shí)候,還是老老實(shí)實(shí)使用redis/mc吧。

 

責(zé)任編輯:武曉燕
相關(guān)推薦

2024-12-26 15:01:29

2022-12-14 08:23:30

2022-07-25 09:48:22

緩存數(shù)據(jù)服務(wù)

2024-10-28 12:41:25

2022-03-29 10:39:10

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

2024-01-15 10:38:20

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

2020-05-12 10:43:22

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

2022-03-31 08:21:14

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

2022-04-01 16:55:22

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

2020-09-03 09:45:38

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

2022-09-06 15:30:20

緩存一致性

2019-03-27 13:56:39

緩存雪崩穿透

2024-04-23 08:22:58

Meta緩存系統(tǒng)

2023-08-15 09:31:01

分布式緩存

2024-04-11 13:45:14

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

2021-12-01 08:26:27

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

2023-08-14 08:10:33

CPU緩存RFO

2021-06-11 09:21:58

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

2025-04-27 08:52:21

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

2024-08-20 16:13:52

點(diǎn)贊
收藏

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