緩存,原來(lái)我們一直都用錯(cuò)了!
緩存,是互聯(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ò)誤用法。
四類緩存常見(jiàn)誤用,你中招了嗎?
誤用一:把緩存作為服務(wù)與服務(wù)之間傳遞數(shù)據(jù)的媒介。
如上圖:
(1)服務(wù)1和服務(wù)2約定好key和value,通過(guò)緩存?zhèn)鬟f數(shù)據(jù);
(2)服務(wù)1將數(shù)據(jù)寫(xiě)入緩存,服務(wù)2從緩存讀取數(shù)據(jù),達(dá)到兩個(gè)服務(wù)通信的目的。
該方案存在的問(wèn)題是:
(1)數(shù)據(jù)管道,數(shù)據(jù)通知場(chǎng)景,MQ更加適合;
(2)多個(gè)服務(wù)關(guān)聯(lián)同一個(gè)緩存實(shí)例,會(huì)導(dǎo)致服務(wù)耦合。
誤用二:使用緩存未考慮雪崩。
常規(guī)的緩存玩法,如上圖:
(1)服務(wù)先讀緩存,緩存命中則返回;
(2)緩存不命中,再讀數(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)移。
方案二:緩存水平切分
如上圖:使用緩存水平切分,一個(gè)緩存實(shí)例掛掉后,不至于所有的流量都?jí)旱綌?shù)據(jù)庫(kù)上。
誤用三:調(diào)用方緩存數(shù)據(jù)。
如上圖:
(1)服務(wù)提供方緩存,向調(diào)用方屏蔽數(shù)據(jù)獲取的復(fù)雜性(這個(gè)沒(méi)問(wèn)題);
(2)服務(wù)調(diào)用方,也緩存一份數(shù)據(jù),先讀自己的緩存,再?zèng)Q定是否調(diào)用服務(wù)(這個(gè)有問(wèn)題)。
該方案存在的問(wèn)題是:
(1)調(diào)用方需要關(guān)注數(shù)據(jù)獲取的復(fù)雜性;
(2)更嚴(yán)重的,服務(wù)修改db里的數(shù)據(jù),淘汰了服務(wù)cache之后,難以通知調(diào)用方淘汰其cache里的數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)不一致;
(3)有人說(shuō),服務(wù)可以通過(guò)MQ通知調(diào)用方淘汰數(shù)據(jù),額,難道下游的服務(wù)要依賴上游的調(diào)用方,分層架構(gòu)設(shè)計(jì)不是這么玩的。
誤用四:多服務(wù)共用緩存實(shí)例。
如上圖:
(1)服務(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í)例要做垂直拆分。
這些坑,你踩過(guò)嗎?
【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】