首先來(lái)了解幾個(gè)概念:
緩存穿透:大量請(qǐng)求根本不存在的key
緩存雪崩:redis中大量key集體過(guò)期
緩存擊穿:redis中一個(gè)熱點(diǎn)key過(guò)期(大量用戶訪問(wèn)該熱點(diǎn)key,但是熱點(diǎn)key過(guò)期)
穿透解決方案
對(duì)空值進(jìn)行緩存
設(shè)置白名單
使用布隆過(guò)濾器
網(wǎng)警
雪崩解決方案
進(jìn)行預(yù)先的熱門詞匯的設(shè)置,進(jìn)行key時(shí)長(zhǎng)的調(diào)整
實(shí)時(shí)調(diào)整,監(jiān)控哪些數(shù)據(jù)是熱門數(shù)據(jù),實(shí)時(shí)的調(diào)整key的過(guò)期時(shí)長(zhǎng)
使用鎖機(jī)制
擊穿解決方案
進(jìn)行預(yù)先的熱門詞匯的設(shè)置,進(jìn)行key時(shí)長(zhǎng)的調(diào)整
實(shí)時(shí)調(diào)整,監(jiān)控哪些數(shù)據(jù)是熱門數(shù)據(jù),實(shí)時(shí)的調(diào)整key的過(guò)期時(shí)長(zhǎng)
使用鎖機(jī)制
三者出現(xiàn)的根本原因在于Redis命中率下降,請(qǐng)求直接打在DB上。
正常情況下,大量的資源請(qǐng)求都會(huì)被redis響應(yīng),在redis得不到響應(yīng)的小部分請(qǐng)求才會(huì)去請(qǐng)求DB,這樣DB的壓力是非常小的,是可以正常工作的(如下圖)
如果大量的請(qǐng)求在redis上得不到響應(yīng),那么就會(huì)導(dǎo)致這些請(qǐng)求會(huì)直接去訪問(wèn)DB,導(dǎo)致DB的壓力瞬間變大而卡死或者宕機(jī)。
大量的高并發(fā)的請(qǐng)求打在redis上
這些請(qǐng)求發(fā)現(xiàn)redis上并沒(méi)有需要請(qǐng)求的資源,redis命中率降低
因此這些大量的高并發(fā)請(qǐng)求轉(zhuǎn)向DB(數(shù)據(jù)庫(kù)服務(wù)器)請(qǐng)求對(duì)應(yīng)的資源
DB壓力瞬間增大,直接將DB打垮,進(jìn)而引發(fā)一系列“災(zāi)害”
如下圖所示
那么為什么redis會(huì)沒(méi)有需要訪問(wèn)的數(shù)據(jù)呢?通過(guò)分析大致可以總結(jié)為三種情況,也就對(duì)應(yīng)著redis的雪崩、穿透和擊穿
情景分析
緩存穿透
緩存穿透產(chǎn)生的原因:請(qǐng)求根本不存在的資源(DB本身就不存在,Redis更是不存在)
舉例(情景在線):客戶端發(fā)送大量的不可響應(yīng)的請(qǐng)求
當(dāng)大量的客戶端發(fā)出類似于:http://localhost:8080/user/19833?id=-3872 的請(qǐng)求,就可能導(dǎo)致出現(xiàn)緩存穿透的情況。因?yàn)閿?shù)據(jù)庫(kù)DB中本身就沒(méi)有id=-3872的用戶的數(shù)據(jù),所以Redis也沒(méi)有對(duì)應(yīng)的數(shù)據(jù),那么這些請(qǐng)求在redis就得不到響應(yīng),就會(huì)直接打在DB上,導(dǎo)致DB壓力過(guò)大而卡死情景在線或宕機(jī)。
緩存穿透很有可能是黑客攻擊所為,黑客通過(guò)發(fā)送大量的高并發(fā)的無(wú)法響應(yīng)的請(qǐng)求給服務(wù)器,由于請(qǐng)求的資源根本就不存在,DB就很容易被打垮了。
解決方案
對(duì)空值進(jìn)行緩存:
類似于上面的例子,雖然數(shù)據(jù)庫(kù)中沒(méi)有id=-3872的用戶的數(shù)據(jù),但是在redis中對(duì)他進(jìn)行緩存(key=-3872,value=null),這樣當(dāng)請(qǐng)求到達(dá)redis的時(shí)候就會(huì)直接返回一個(gè)null的值給客戶端,避免了大量無(wú)法訪問(wèn)的數(shù)據(jù)直接打在DB上
實(shí)時(shí)監(jiān)控:
對(duì)redis進(jìn)行實(shí)時(shí)監(jiān)控,當(dāng)發(fā)現(xiàn)redis中的命中率下降的時(shí)候進(jìn)行原因的排查,配合運(yùn)維人員對(duì)訪問(wèn)對(duì)象和訪問(wèn)數(shù)據(jù)進(jìn)行分析查詢,從而進(jìn)行黑名單的設(shè)置限制服務(wù)(拒絕黑客攻擊)
使用布隆過(guò)濾器
使用BitMap作為布隆過(guò)濾器,將目前所有可以訪問(wèn)到的資源通過(guò)簡(jiǎn)單的映射關(guān)系放入到布隆過(guò)濾器中(哈希計(jì)算),當(dāng)一個(gè)請(qǐng)求來(lái)臨的時(shí)候先進(jìn)行布隆過(guò)濾器的判斷,如果有那么才進(jìn)行放行,否則就直接攔截
接口校驗(yàn)
類似于用戶權(quán)限的攔截,對(duì)于id=-3872這些無(wú)效訪問(wèn)就直接攔截,不允許這些請(qǐng)求到達(dá)Redis、DB上。
注意事項(xiàng):
使用空值作為緩存的時(shí)候,key設(shè)置的過(guò)期時(shí)間不能太長(zhǎng),防止占用太多redis資源
使用空值作為緩存只能防止黑客重復(fù)使用相同的id暴力攻擊,但是如果黑客使用動(dòng)態(tài)的無(wú)效id攻擊就沒(méi)有效果(需要配合網(wǎng)警)
使用布隆過(guò)濾器也是有哈希沖突的可能
緩存雪崩
緩存雪崩產(chǎn)生的原因:redis中大量的key集體過(guò)期
舉例:
當(dāng)redis中的大量key集體過(guò)期,可以理解為redis中的大部分?jǐn)?shù)據(jù)都被清空了(失效了),那么這時(shí)候如果有大量并發(fā)的請(qǐng)求來(lái)到,那么redis就無(wú)法進(jìn)行有效的響應(yīng)(命中率急劇下降),請(qǐng)求就都打到DB上了,到時(shí)DB直接崩潰。
解決方案:
將失效時(shí)間分散開
通過(guò)使用自動(dòng)生成隨機(jī)數(shù)使得key的過(guò)期時(shí)間是隨機(jī)的,防止集體過(guò)期
使用多級(jí)架構(gòu)
使用nginx緩存+redis緩存+其他緩存,不同層使用不同的緩存,可靠性更強(qiáng)
設(shè)置緩存標(biāo)記
記錄緩存數(shù)據(jù)是否過(guò)期,如果過(guò)期會(huì)觸發(fā)通知另外的線程在后臺(tái)去跟新實(shí)際的key
使用鎖或者隊(duì)列的方式
如果查不到就加上排它鎖,其他請(qǐng)求只能進(jìn)行等待
緩存擊穿
產(chǎn)生緩存雪崩的原因:redis中的某個(gè)熱點(diǎn)key過(guò)期,但是此時(shí)有大量的用戶訪問(wèn)該過(guò)期key
舉例:
類似于“某男明星塌房事件”上了熱搜,這時(shí)候大量的“粉絲”都在訪問(wèn)該熱點(diǎn)事件,但是可能優(yōu)于某種原因,redis的這個(gè)熱點(diǎn)key過(guò)期了,那么這時(shí)候大量高并發(fā)對(duì)于該key的請(qǐng)求就得不到redis的響應(yīng),那么就會(huì)將請(qǐng)求直接打在DB服務(wù)器上,導(dǎo)致整個(gè)DB癱瘓。
解決方案:
提前對(duì)熱點(diǎn)數(shù)據(jù)進(jìn)行設(shè)置
類似于新聞、某博等軟件都需要對(duì)熱點(diǎn)數(shù)據(jù)進(jìn)行預(yù)先設(shè)置在redis中
監(jiān)控?cái)?shù)據(jù),適時(shí)調(diào)整
監(jiān)控哪些數(shù)據(jù)是熱門數(shù)據(jù),實(shí)時(shí)的調(diào)整key的過(guò)期時(shí)長(zhǎng)
使用鎖機(jī)制
最后的防線,當(dāng)熱點(diǎn)key過(guò)期,那么就使用鎖機(jī)制防止大量的請(qǐng)求直接打在DB
-
緩存
+關(guān)注
關(guān)注
1文章
242瀏覽量
26767 -
過(guò)濾器
+關(guān)注
關(guān)注
1文章
433瀏覽量
19743 -
key
+關(guān)注
關(guān)注
0文章
51瀏覽量
12862
原文標(biāo)題:緩存被穿透了怎么辦?
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論