這篇文章主要講解了“怎么解決redis緩存雪崩、擊穿與穿透問(wèn)題”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“怎么解決Redis緩存雪崩、擊穿與穿透問(wèn)題”吧!
目前創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、永靖網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
緩存雪崩
是指大量的請(qǐng)求無(wú)法命中Redis
中的緩存數(shù)據(jù),也就是在Redis
找不到數(shù)據(jù)了,那業(yè)務(wù)系統(tǒng)只能到數(shù)據(jù)庫(kù)中查詢,進(jìn)而導(dǎo)致所有的請(qǐng)求都發(fā)送到了數(shù)據(jù)庫(kù)。如下圖所示:
數(shù)據(jù)庫(kù)并不像Redis
能處理大量請(qǐng)求,由緩存雪崩導(dǎo)致的請(qǐng)求激增必須會(huì)導(dǎo)致數(shù)據(jù)庫(kù)所在宕機(jī),這樣勢(shì)必會(huì)影響業(yè)務(wù)系統(tǒng),所以如果發(fā)生緩存雪崩,對(duì)于業(yè)務(wù)系統(tǒng)肯定是致命的。
什么情況下出現(xiàn)緩存雪崩呢?總結(jié)起來(lái)有以下兩個(gè)方面的原因:
大量Redis
緩存數(shù)據(jù)同時(shí)過(guò)期,導(dǎo)致所有的發(fā)送到Redis
請(qǐng)求都無(wú)法命中數(shù)據(jù),只能到數(shù)據(jù)庫(kù)中進(jìn)行查詢。
Redis
服務(wù)器宕機(jī),所有請(qǐng)求都無(wú)法經(jīng)Redis
來(lái)處理,只能轉(zhuǎn)向數(shù)據(jù)庫(kù)查詢數(shù)據(jù)。
針對(duì)導(dǎo)致緩存雪崩的原因,有不同的解決方法:
針對(duì)大量緩存隨機(jī)過(guò)期時(shí)間,解決方法就是在原始過(guò)期時(shí)間的基礎(chǔ)上,再加一個(gè)隨機(jī)過(guò)期時(shí)間,比如1到5分鐘之間的隨機(jī)過(guò)期時(shí)間,這樣可以避免大量的緩存數(shù)據(jù)在同一時(shí)間過(guò)期。
而針對(duì)Redis
解決宕機(jī)的導(dǎo)致的緩存雪崩,可以提前搭建好Redis
的主從服務(wù)器進(jìn)行數(shù)據(jù)同步,并配置哨兵機(jī)制,這樣在Redis
服務(wù)器因?yàn)殄礄C(jī)而無(wú)法提供服務(wù)時(shí),可以由哨兵將Redis
從服務(wù)器設(shè)置為主服務(wù)器,繼續(xù)提供服務(wù)。
緩存擊穿與緩存雪崩的情況相似,雪崩是因?yàn)榇罅康臄?shù)據(jù)過(guò)期,而緩存擊穿則是指熱點(diǎn)數(shù)據(jù)過(guò)期,所有針對(duì)熱點(diǎn)數(shù)據(jù)的請(qǐng)求都需要到數(shù)據(jù)庫(kù)中進(jìn)行處理,如下圖所示:
解決緩存擊穿的三種方式:
不設(shè)置過(guò)期時(shí)間
如果我們能提前知道某個(gè)數(shù)據(jù)是熱點(diǎn)數(shù)據(jù),那么就可以不設(shè)置這些數(shù)據(jù)的過(guò)期,從而避免緩存擊穿問(wèn)題,比如一些秒殺活動(dòng)的商品,在秒殺時(shí)會(huì)大量用戶訪問(wèn),這時(shí)候我們就可以將這些用于秒殺的商品數(shù)據(jù)提前寫(xiě)入緩存并且不設(shè)置過(guò)期時(shí)間。
互斥鎖
提前知道某些數(shù)據(jù)會(huì)有大量訪問(wèn),我們當(dāng)然可以設(shè)置不過(guò)期,但更多時(shí)候,我們并不能提前預(yù)知,這種情況要怎么處理呢?
我們來(lái)分析一下緩存擊穿的情況:
正常情況下,當(dāng)某個(gè)Redis
緩存數(shù)據(jù)過(guò)期時(shí),如果有對(duì)該數(shù)據(jù)的請(qǐng)求,則重新到數(shù)據(jù)庫(kù)中查詢并再寫(xiě)入緩存,讓后續(xù)的請(qǐng)求可以命中該緩存而無(wú)須再去數(shù)據(jù)庫(kù)中查詢。
而熱點(diǎn)數(shù)據(jù)過(guò)期時(shí),由于大量請(qǐng)求,當(dāng)某個(gè)請(qǐng)求無(wú)法命中緩存時(shí),會(huì)去查詢數(shù)據(jù)庫(kù)并重新把數(shù)據(jù)寫(xiě)入Redis
,也就是在寫(xiě)入Redis
之前,其他請(qǐng)求進(jìn)來(lái),也會(huì)去查詢數(shù)據(jù)庫(kù)。
好了,我們知道熱點(diǎn)數(shù)據(jù)過(guò)期后,很多請(qǐng)求會(huì)去查詢數(shù)據(jù)庫(kù),那么我們可以給去查詢數(shù)據(jù)庫(kù)的業(yè)務(wù)邏輯加個(gè)互斥鎖,只有獲得鎖的請(qǐng)求才能去查詢數(shù)據(jù)庫(kù)并把數(shù)據(jù)寫(xiě)回Redis
,而其他沒(méi)有獲得鎖的請(qǐng)求只能等待數(shù)據(jù)就緒。
上述步驟的如下圖所示:
設(shè)置邏輯過(guò)期時(shí)間
使用互斥鎖雖然可以非常簡(jiǎn)單地解決緩存擊穿問(wèn)題,但沒(méi)有獲得鎖的請(qǐng)求雖然排隊(duì)等待,這樣影響了系統(tǒng)的性能,還有另一種解決緩存擊穿的方法就是在業(yè)務(wù)數(shù)據(jù)冗余一個(gè)過(guò)期時(shí)間,比如下面的數(shù)據(jù)中我們?cè)黾恿?code>expire_at字段用于表示數(shù)據(jù)過(guò)期時(shí)間。
{"name":"test","expire_at":"1599999999"}復(fù)制代碼
這種方式的實(shí)現(xiàn)過(guò)程如下圖所示:
緩存中的熱點(diǎn)數(shù)據(jù)中冗余一個(gè)邏輯過(guò)期時(shí)間,但數(shù)據(jù)在Redis
不設(shè)置過(guò)期時(shí)間
當(dāng)一個(gè)請(qǐng)求拿到Redis
中的數(shù)據(jù)時(shí),判斷邏輯過(guò)期時(shí)間是否到期,如果沒(méi)有到期,直接返回,如果到期則開(kāi)啟另一個(gè)線程獲得鎖后去查詢數(shù)據(jù)庫(kù)并將查詢的最新數(shù)據(jù)寫(xiě)回Redis
,而當(dāng)前請(qǐng)求返回已經(jīng)查詢的數(shù)據(jù)。
緩存穿透是指要查找的數(shù)據(jù)既不在緩存當(dāng)中,也不在數(shù)據(jù)庫(kù)中,因?yàn)椴辉诰彺嬷?,所以?qǐng)求一定會(huì)到達(dá)數(shù)據(jù)庫(kù),Redis
緩存形同虛設(shè),如下圖所示:
什么條件下會(huì)發(fā)生緩存穿透呢?主要有以下三種情況:
用戶惡意攻擊請(qǐng)求
誤操作把Redis
和數(shù)據(jù)庫(kù)里的數(shù)據(jù)刪除了
用戶還未產(chǎn)生內(nèi)容時(shí),比如用戶的文章列表,用戶還未寫(xiě)文章,所以緩存和數(shù)據(jù)庫(kù)都沒(méi)有數(shù)據(jù)
當(dāng)在Redis
緩存中查詢不到數(shù)據(jù)時(shí),再?gòu)臄?shù)據(jù)庫(kù)查詢,如果同樣沒(méi)有數(shù)據(jù),就直接緩存一個(gè)空間或缺省值,這樣可以避免下次再去查詢數(shù)據(jù)庫(kù);不過(guò)為了防止之后已經(jīng)數(shù)據(jù)庫(kù)已經(jīng)相應(yīng)數(shù)據(jù)庫(kù),再返回空值問(wèn)題,應(yīng)該為緩存設(shè)置過(guò)期時(shí)間,或者在產(chǎn)生數(shù)據(jù)時(shí)直接清除對(duì)應(yīng)的緩存空值。
雖然緩存空值可以解決緩存穿透問(wèn)題,但仍然需要查詢一次數(shù)據(jù)庫(kù)才能確定是否有數(shù)據(jù),如果有用戶惡意攻擊,高并發(fā)地使用系統(tǒng)不存在的數(shù)據(jù)id進(jìn)行查詢,所有的查詢都要經(jīng)過(guò)數(shù)據(jù)庫(kù),這樣仍然會(huì)給數(shù)據(jù)庫(kù)帶來(lái)很大的壓力。
所以,有沒(méi)有不用查詢數(shù)據(jù)庫(kù)就能確定數(shù)據(jù)是否存在的辦法呢?有的,用布隆過(guò)濾器
。
布隆過(guò)濾器主要是兩個(gè)部分:bit數(shù)組+N個(gè)哈希函數(shù),其原理為:
使用N個(gè)哈希函數(shù)對(duì)所要標(biāo)記的數(shù)據(jù)進(jìn)行哈希值計(jì)算。
將計(jì)算到的哈希值對(duì)bit數(shù)組的長(zhǎng)度取模,這樣可以得到每個(gè)哈希值在bit數(shù)組的位置。
把bit數(shù)組中對(duì)應(yīng)的位置標(biāo)記為1。
下面是布隆過(guò)濾器原理示意圖:
當(dāng)要進(jìn)行數(shù)據(jù)寫(xiě)入時(shí),執(zhí)行述述步驟,計(jì)算對(duì)應(yīng)bit數(shù)組位置并標(biāo)識(shí)為1,那么在執(zhí)行查詢時(shí),就能查詢?cè)摂?shù)據(jù)是否存在了。
另外,由于哈希碰撞問(wèn)題導(dǎo)致的誤差,所以不存在的數(shù)據(jù)經(jīng)過(guò)布隆過(guò)濾器后,會(huì)被判定為存在,再去查數(shù)據(jù)庫(kù),不過(guò)哈希碰到的概率很小,用布隆過(guò)濾器已經(jīng)能幫我們攔截大部分的穿透請(qǐng)求了。
Redis
本身就支持布隆過(guò)濾器,所以我們可以直接使用Redis
布隆過(guò)濾器,而不用自己去實(shí)現(xiàn),非常方便。
緩存的雪崩、擊穿、穿透是在業(yè)務(wù)應(yīng)用緩存時(shí)經(jīng)常會(huì)碰到的緩存異常問(wèn)題,其原因與解決方法如以下表示所示:
問(wèn)題 | 原因 | 解決方法 |
---|---|---|
緩存雪崩 | 大量數(shù)據(jù)過(guò)期或Redis 服務(wù)器宕機(jī) | 1. 隨機(jī)過(guò)期時(shí)間 2. 主從+哨兵的集群 |
緩存擊穿 | 熱點(diǎn)數(shù)據(jù)過(guò)期 | 1. 不設(shè)置過(guò)期時(shí)間 2. 加互斥鎖 3. 冗余邏輯過(guò)期時(shí)間 |
緩存穿透 | 請(qǐng)求數(shù)據(jù)庫(kù)和Redis 都沒(méi)有的數(shù)據(jù) | 1. 緩存空值或缺省值 2. 布隆過(guò)濾器 |
感謝各位的閱讀,以上就是“怎么解決Redis緩存雪崩、擊穿與穿透問(wèn)題”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)怎么解決Redis緩存雪崩、擊穿與穿透問(wèn)題這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
分享名稱(chēng):怎么解決Redis緩存雪崩、擊穿與穿透問(wèn)題
瀏覽地址:http://sd-ha.com/article32/jgijpc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站內(nèi)鏈、全網(wǎng)營(yíng)銷(xiāo)推廣、微信公眾號(hào)、企業(yè)建站、用戶體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)