redis 缓存预热_Redis:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
一、緩存雪崩
緩存雪崩我們可以簡(jiǎn)單的理解為:由于原有緩存失效,新緩存未到期間(例如:我們?cè)O(shè)置緩存時(shí)采用了相同的過期時(shí)間,在同一時(shí)刻出現(xiàn)大面積的緩存過期),所有原本應(yīng)該訪問緩存的請(qǐng)求都去查詢數(shù)據(jù)庫(kù)了,而對(duì)數(shù)據(jù)庫(kù)CPU和內(nèi)存造成巨大壓力,嚴(yán)重的會(huì)造成數(shù)據(jù)庫(kù)宕機(jī)。從而形成一系列連鎖反應(yīng),造成整個(gè)系統(tǒng)崩潰。
緩存正常從Redis中獲取,示意圖如下:
緩存失效瞬間示意圖如下:
緩存雪崩的解決方案:
(1)碰到這種情況,一般并發(fā)量不是特別多的時(shí)候,使用最多的解決方案是加鎖排隊(duì),偽代碼如下:
加鎖排隊(duì)只是為了減輕數(shù)據(jù)庫(kù)的壓力,并沒有提高系統(tǒng)吞吐量。假設(shè)在高并發(fā)下,緩存重建期間key是鎖著的,這是過來1000個(gè)請(qǐng)求999個(gè)都在阻塞的。同樣會(huì)導(dǎo)致用戶等待超時(shí),這是個(gè)治標(biāo)不治本的方法!
注意:加鎖排隊(duì)的解決方式分布式環(huán)境的并發(fā)問題,有可能還要解決分布式鎖的問題;線程還會(huì)被阻塞,用戶體驗(yàn)很差!因此,在真正的高并發(fā)場(chǎng)景下很少使用!
(2)給每一個(gè)緩存數(shù)據(jù)增加相應(yīng)的緩存標(biāo)記,記錄緩存的是否失效,如果緩存標(biāo)記失效,則更新數(shù)據(jù)緩存,實(shí)例偽代碼如下:
解釋說明:
1、緩存標(biāo)記:記錄緩存數(shù)據(jù)是否過期,如果過期會(huì)觸發(fā)通知另外的線程在后臺(tái)去更新實(shí)際key的緩存;
2、緩存數(shù)據(jù):它的過期時(shí)間比緩存標(biāo)記的時(shí)間延長(zhǎng)1倍,例:標(biāo)記緩存時(shí)間30分鐘,數(shù)據(jù)緩存設(shè)置為60分鐘。 這樣,當(dāng)緩存標(biāo)記key過期后,實(shí)際緩存還能把舊數(shù)據(jù)返回給調(diào)用端,直到另外的線程在后臺(tái)更新完成后,才會(huì)返回新緩存。
關(guān)于緩存崩潰的解決方法,這里提出了三種方案:使用鎖或隊(duì)列、設(shè)置過期標(biāo)志更新緩存、為key設(shè)置不同的緩存失效時(shí)間,還有一各被稱為“二級(jí)緩存”的解決方法,有興趣的讀者可以自行研究。
二、緩存穿透
緩存穿透是指用戶查詢數(shù)據(jù),在數(shù)據(jù)庫(kù)沒有,自然在緩存中也不會(huì)有。這樣就導(dǎo)致用戶查詢的時(shí)候,在緩存中找不到,每次都要去數(shù)據(jù)庫(kù)再查詢一遍,然后返回空(相當(dāng)于進(jìn)行了兩次無用的查詢)。這樣請(qǐng)求就繞過緩存直接查數(shù)據(jù)庫(kù),這也是經(jīng)常提的緩存命中率問題。
緩存穿透解決方案:
(1)采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè)bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。
(2)如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過期時(shí)間會(huì)很短,最長(zhǎng)不超過五分鐘。通過這個(gè)直接設(shè)置的默認(rèn)值存放到緩存,這樣第二次到緩存中獲取就有值了,而不會(huì)繼續(xù)訪問數(shù)據(jù)庫(kù),這種辦法最簡(jiǎn)單粗暴!
把空結(jié)果也給緩存起來,這樣下次同樣的請(qǐng)求就可以直接返回空了,即可以避免當(dāng)查詢的值為空時(shí)引起的緩存穿透。同時(shí)也可以單獨(dú)設(shè)置個(gè)緩存區(qū)域存儲(chǔ)空值,對(duì)要查詢的key進(jìn)行預(yù)先校驗(yàn),然后再放行給后面的正常緩存處理邏輯。
三、緩存預(yù)熱
緩存預(yù)熱就是系統(tǒng)上線后,提前將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。避免在用戶請(qǐng)求的時(shí)候,先查詢數(shù)據(jù)庫(kù),然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)!
緩存預(yù)熱解決方案:
(1)直接寫個(gè)緩存刷新頁面,上線時(shí)手工操作下;
(2)數(shù)據(jù)量不大,可以在項(xiàng)目啟動(dòng)的時(shí)候自動(dòng)進(jìn)行加載;
(3)定時(shí)刷新緩存;
四、緩存更新
除了緩存服務(wù)器自帶的緩存失效策略之外(Redis默認(rèn)的有6中策略可供選擇),我們還可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行自定義的緩存淘汰,常見的策略有兩種:
(1)定時(shí)去清理過期的緩存;
(2)當(dāng)有用戶請(qǐng)求過來時(shí),再判斷這個(gè)請(qǐng)求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存。
兩者各有優(yōu)劣,第一種的缺點(diǎn)是維護(hù)大量緩存的key是比較麻煩的,第二種的缺點(diǎn)就是每次用戶請(qǐng)求過來都要判斷緩存失效,邏輯相對(duì)比較復(fù)雜!具體用哪種方案,大家可以根據(jù)自己的應(yīng)用場(chǎng)景來權(quán)衡。
五、緩存降級(jí)
當(dāng)訪問量劇增、服務(wù)出現(xiàn)問題(如響應(yīng)時(shí)間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時(shí),仍然需要保證服務(wù)還是可用的,即使是有損服務(wù)。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動(dòng)降級(jí),也可以配置開關(guān)實(shí)現(xiàn)人工降級(jí)。
降級(jí)的最終目的是保證核心服務(wù)可用,即使是有損的。而且有些服務(wù)是無法降級(jí)的(如加入購(gòu)物車、結(jié)算)。
在進(jìn)行降級(jí)之前要對(duì)系統(tǒng)進(jìn)行梳理,看看系統(tǒng)是不是可以丟卒保帥;從而梳理出哪些必須誓死保護(hù),哪些可降級(jí);比如可以參考日志級(jí)別設(shè)置預(yù)案:
(1)一般:比如有些服務(wù)偶爾因?yàn)榫W(wǎng)絡(luò)抖動(dòng)或者服務(wù)正在上線而超時(shí),可以自動(dòng)降級(jí);
(2)警告:有些服務(wù)在一段時(shí)間內(nèi)成功率有波動(dòng)(如在95~100%之間),可以自動(dòng)降級(jí)或人工降級(jí),并發(fā)送告警;
(3)錯(cuò)誤:比如可用率低于90%,或者數(shù)據(jù)庫(kù)連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時(shí)可以根據(jù)情況自動(dòng)降級(jí)或者人工降級(jí);
(4)嚴(yán)重錯(cuò)誤:比如因?yàn)樘厥庠驍?shù)據(jù)錯(cuò)誤了,此時(shí)需要緊急人工降級(jí)。
總結(jié)
以上是生活随笔為你收集整理的redis 缓存预热_Redis:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: python视频延迟严重_利用多进程降低
- 下一篇: Java一个小练习----String类
