Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
Java相關(guān)的面試都會問到緩存的問題:史上最全Redis面試49題(含答案):哨兵+復(fù)制+事務(wù)+集群+持久化等,除此之外還會問到緩存雪崩、緩存穿透、緩存預(yù)熱、緩存更新、緩存降級等不常見的問題,但卻是非常重要的問題,今天談?wù)勥@個話題。
基本看完這兩篇,可以對redis有一個比較全面的初步了解,后續(xù)我再補(bǔ)充redis相關(guān)的實(shí)戰(zhàn)篇,總結(jié)為一個redis系列。
緩存雪崩
數(shù)據(jù)未加載到緩存中,或者緩存同一時間大面積的失效,從而導(dǎo)致所有請求都去查數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫CPU和內(nèi)存負(fù)載過高,甚至宕機(jī)。
比如一個雪崩的簡單過程:
1、redis集群大面積故障
2、緩存失效,但依然大量請求訪問緩存服務(wù)redis
3、redis大量失效后,大量請求轉(zhuǎn)向到mysql數(shù)據(jù)庫
4、mysql的調(diào)用量暴增,很快就扛不住了,甚至直接宕機(jī)
5、由于大量的應(yīng)用服務(wù)依賴mysql和redis的服務(wù),這個時候很快會演變成各服務(wù)器集群的雪崩,最后網(wǎng)站徹底崩潰。
如何預(yù)防緩存雪崩:
1.緩存的高可用性
緩存層設(shè)計成高可用,防止緩存大面積故障。即使個別節(jié)點(diǎn)、個別機(jī)器、甚至是機(jī)房宕掉,依然可以提供服務(wù),例如 Redis Sentinel 和 Redis Cluster 都實(shí)現(xiàn)了高可用。
2.緩存降級
可以利用ehcache等本地緩存(暫時支持),但主要還是對源服務(wù)訪問進(jìn)行限流、資源隔離(熔斷)、降級等。
當(dāng)訪問量劇增、服務(wù)出現(xiàn)問題仍然需要保證服務(wù)還是可用的。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動降級,也可以配置開關(guān)實(shí)現(xiàn)人工降級,這里會涉及到運(yùn)維的配合。
降級的最終目的是保證核心服務(wù)可用,即使是有損的。
比如推薦服務(wù)中,很多都是個性化的需求,假如個性化需求不能提供服務(wù)了,可以降級補(bǔ)充熱點(diǎn)數(shù)據(jù),不至于造成前端頁面是個大空白。
在進(jìn)行降級之前要對系統(tǒng)進(jìn)行梳理,比如:哪些業(yè)務(wù)是核心(必須保證),哪些業(yè)務(wù)可以容許暫時不提供服務(wù)(利用靜態(tài)頁面替換)等,以及配合服務(wù)器核心指標(biāo),來后設(shè)置整體預(yù)案,比如:
(1)一般:比如有些服務(wù)偶爾因?yàn)榫W(wǎng)絡(luò)抖動或者服務(wù)正在上線而超時,可以自動降級;
(2)警告:有些服務(wù)在一段時間內(nèi)成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發(fā)送告警;
(3)錯誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時可以根據(jù)情況自動降級或者人工降級;
(4)嚴(yán)重錯誤:比如因?yàn)樘厥庠驍?shù)據(jù)錯誤了,此時需要緊急人工降級。
3.Redis備份和快速預(yù)熱
1)Redis數(shù)據(jù)備份和恢復(fù)
2)快速緩存預(yù)熱
4.提前演練
最后,建議還是在項(xiàng)目上線前,演練緩存層宕掉后,應(yīng)用以及后端的負(fù)載情況以及可能出現(xiàn)的問題,對高可用提前預(yù)演,提前發(fā)現(xiàn)問題。
緩存穿透
緩存穿透是指查詢一個一不存在的數(shù)據(jù)。例如:從緩存redis沒有命中,需要從mysql數(shù)據(jù)庫查詢,查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個不存在的數(shù)據(jù)每次請求都要到數(shù)據(jù)庫去查詢,造成緩存穿透。
解決思路:
如果查詢數(shù)據(jù)庫也為空,直接設(shè)置一個默認(rèn)值存放到緩存,這樣第二次到緩沖中獲取就有值了,而不會繼續(xù)訪問數(shù)據(jù)庫。設(shè)置一個過期時間或者當(dāng)有值的時候?qū)⒕彺嬷械闹堤鎿Q掉即可。
可以給key設(shè)置一些格式規(guī)則,然后查詢之前先過濾掉不符合規(guī)則的Key。
緩存并發(fā)
這里的并發(fā)指的是多個redis的client同時set
key引起的并發(fā)問題。其實(shí)redis自身就是單線程操作,多個client并發(fā)操作,按照先到先執(zhí)行的原則,先到的先執(zhí)行,其余的阻塞。當(dāng)然,另外的解決方案是把redis.set操作放在隊列中使其串行化,必須的一個一個執(zhí)行。
緩存預(yù)熱
緩存預(yù)熱就是系統(tǒng)上線后,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。
這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)!
解決思路:
1、直接寫個緩存刷新頁面,上線時手工操作下;
2、數(shù)據(jù)量不大,可以在項(xiàng)目啟動的時候自動進(jìn)行加載;
目的就是在系統(tǒng)上線前,將數(shù)據(jù)加載到緩存中。
以上就是緩存雪崩、預(yù)熱、降級等的介紹,更多整體從服務(wù)器雪崩的角度,具體可以參考:阿里P8架構(gòu)師談:什么是緩存雪崩?服務(wù)器雪崩的場景與解決方案
你可能也喜歡:
總結(jié)
以上是生活随笔為你收集整理的Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里P8架构师谈:从单体架构、到SOA、
- 下一篇: 阿里P8架构师谈:多线程、架构、异步消息