緩存擊穿、穿透、雪崩及解決方案
Redis是一種高性能的鍵值型數(shù)據(jù)庫,它可以用來實(shí)現(xiàn)緩存功能,提高應(yīng)用的響應(yīng)速度和承載能力。但是,使用Redis緩存也會(huì)遇到一些常見的問題,比如緩存擊穿、緩存穿透、緩存雪崩。這些問題都會(huì)影響緩存的效率和穩(wěn)定性,所以需要了解它們的原因和解決方案,保障Redis能夠正常運(yùn)行。
擊穿、穿透、雪崩的意思
擊穿、穿透、雪崩這三個(gè)詞語很容易混淆,本文先對(duì)詞語進(jìn)行理解,再講解技術(shù)
擊穿:擊穿拆開后,是擊和穿。擊意為敲打,或做類似敲打的動(dòng)作。穿意為穿透
擊是什么?如下圖,攻擊的意思
穿是什么?如下圖,穿透,造成的效果就是個(gè)洞
雪崩的意思很簡單,就是一個(gè)字多,如下圖
白話講解一下,擊穿就是先擊后穿;穿透就是穿透,有個(gè)洞;雪崩就是多,很多很多
再從技術(shù)角度說明擊穿、穿透、雪崩
擊穿意為先擊后穿。熱點(diǎn)數(shù)據(jù)存在,且能夠擊中。但是由于熱點(diǎn)數(shù)據(jù)失效從而訪問數(shù)據(jù)庫
穿透意為直接穿。由于訪問不存在的數(shù)據(jù),從而直接訪問數(shù)據(jù)庫
雪崩意為多,大量。大量緩存同時(shí)失效,從而直接訪問數(shù)據(jù)庫
緩存擊穿
緩存擊穿的定義:某個(gè)熱點(diǎn)數(shù)據(jù)在緩存中過期或失效時(shí),大量的請(qǐng)求同時(shí)訪問該數(shù)據(jù),導(dǎo)致數(shù)據(jù)庫壓力過大甚至崩潰的現(xiàn)象。通常會(huì)發(fā)生在數(shù)據(jù)更新頻率較高或者緩存設(shè)置了相同的過期時(shí)間的時(shí)候。
實(shí)際上可以這么理解:應(yīng)該有的數(shù)據(jù)但是沒讀到,從而擊穿了緩存,直接訪問數(shù)據(jù)庫
可采取的方案:
- 不設(shè)置過期時(shí)間或設(shè)置較長的過期時(shí)間:這樣可以避免熱點(diǎn)數(shù)據(jù)同時(shí)失效,但是也會(huì)增加內(nèi)存占用和數(shù)據(jù)不一致的風(fēng)險(xiǎn)
- 定時(shí)更新。比如這個(gè)熱點(diǎn)數(shù)據(jù)的過期時(shí)間是 2 小時(shí),那么每到 1小時(shí)50 分鐘時(shí),通過定時(shí)任務(wù)去更新這個(gè)熱點(diǎn) key,并重新設(shè)置其過期時(shí)間
- 互斥鎖:當(dāng)緩存中沒有數(shù)據(jù)時(shí),只允許一個(gè)線程去數(shù)據(jù)庫查詢并更新緩存,其他線程等待該線程完成后再從緩存中獲取數(shù)據(jù)。這樣可以減少對(duì)數(shù)據(jù)庫的并發(fā)訪問,但是也會(huì)降低系統(tǒng)的吞吐量和響應(yīng)速度
- 分布式鎖:當(dāng)多個(gè)Redis節(jié)點(diǎn)存在時(shí),可以使用分布式鎖來保證只有一個(gè)節(jié)點(diǎn)去數(shù)據(jù)庫查詢并更新緩存,其他節(jié)點(diǎn)等待該節(jié)點(diǎn)完成后再從緩存中獲取數(shù)據(jù)。這樣可以避免多個(gè)Redis節(jié)點(diǎn)同時(shí)訪問數(shù)據(jù)庫,但是也會(huì)增加系統(tǒng)的復(fù)雜度和延遲
緩存穿透
緩存穿透的定義:
用戶查詢一個(gè)不存在的數(shù)據(jù),導(dǎo)致緩存中沒有該數(shù)據(jù),每次都要去數(shù)據(jù)庫查詢,而數(shù)據(jù)庫中也沒有該數(shù)據(jù),造成無效的查詢和資源浪費(fèi)的現(xiàn)象。通常會(huì)發(fā)生在用戶惡意攻擊或者參數(shù)校驗(yàn)不嚴(yán)格的時(shí)候
實(shí)際上可以這么理解:不應(yīng)該有的數(shù)據(jù)非要讀,從而穿透了緩存,直接訪問數(shù)據(jù)庫
可采取的方案:
- 業(yè)務(wù)層校驗(yàn)。用戶發(fā)過來的請(qǐng)求,根據(jù)請(qǐng)求參數(shù)進(jìn)行校驗(yàn),對(duì)于明顯錯(cuò)誤的參數(shù),直接攔截返回。比如請(qǐng)求參數(shù)為主鍵自增 id ,那么對(duì)于請(qǐng)求小于 0 的 id 參數(shù), 明顯不符合業(yè)務(wù)邏輯。
- 緩存空值:當(dāng)數(shù)據(jù)庫中沒有查詢到數(shù)據(jù)時(shí),仍然將空值或者默認(rèn)值寫入緩存,并設(shè)置一個(gè)較短的過期時(shí)間。這樣可以減少對(duì)數(shù)據(jù)庫的訪問次數(shù),但也會(huì)占用一定的內(nèi)存
- 使用布隆過濾器:布隆過濾器是一種概率型的數(shù)據(jù)結(jié)構(gòu),它可以判斷一個(gè)元素是否可能存在于一個(gè)集合中??梢詫⑺锌赡艽嬖诘臄?shù)據(jù)的鍵值哈希到一個(gè)足夠大的位圖中,當(dāng)用戶查詢一個(gè)數(shù)據(jù)時(shí),先用布隆過濾器判斷該鍵值是否可能存在,如果不存在則直接返回,如果存在則再去緩存和數(shù)據(jù)庫中查詢。這樣可以有效地?cái)r截不存在的數(shù)據(jù)請(qǐng)求,但是也會(huì)有一定的誤判率和內(nèi)存開銷
緩存雪崩
緩存雪崩的定義:在某個(gè)時(shí)間點(diǎn),大量的緩存數(shù)據(jù)同時(shí)失效或者緩存服務(wù)器宕機(jī),導(dǎo)致所有的請(qǐng)求都要去數(shù)據(jù)庫查詢,造成數(shù)據(jù)庫壓力過大甚至崩潰的現(xiàn)象。這種情況通常發(fā)生在緩存設(shè)置了相同或者相近的過期時(shí)間或者緩存服務(wù)器遭遇意外故障的場景下。
實(shí)際上可以這么理解:大量數(shù)據(jù)讀取,從而使緩存雪崩,直接訪問數(shù)據(jù)庫
為了防止緩存雪崩,可以采用以下幾種方法:文章來源:http://www.zghlxwxcb.cn/news/detail-464315.html
- 設(shè)置不同的過期時(shí)間??梢越o緩存設(shè)置不同或者隨機(jī)的過期時(shí)間,避免大量的緩存同時(shí)失效,造成數(shù)據(jù)庫壓力突增
- 緩存預(yù)熱:對(duì)于即將來臨的大量請(qǐng)求,可以將數(shù)據(jù)提前緩存在Redis中,并設(shè)置不同的過期時(shí)間
- 使用多級(jí)緩存:可以構(gòu)建多級(jí)緩存架構(gòu),比如Nginx緩存+Redis緩存+本地緩存等,當(dāng)某一級(jí)緩存出現(xiàn)問題時(shí),可以從其他級(jí)別的緩存中獲取數(shù)據(jù),增加系統(tǒng)的容錯(cuò)能力
- 使用限流熔斷:可以利用一些限流和熔斷組件,對(duì)請(qǐng)求進(jìn)行限流和降級(jí)處理,當(dāng)請(qǐng)求超過系統(tǒng)能承受的閥值時(shí),直接拒絕或者返回默認(rèn)值,保護(hù)數(shù)據(jù)庫不被打垮
- 使用集群和負(fù)載均衡:可以將Redis部署成集群模式,并使用負(fù)載均衡組件,比如LVS、HAProxy等,對(duì)請(qǐng)求進(jìn)行分發(fā)和轉(zhuǎn)發(fā),提高Redis的可用性和并發(fā)能力
總結(jié)
本文介紹了緩存擊穿、緩存穿透和緩存雪崩三種問題及解決方案。通過本文,可以了解到:文章來源地址http://www.zghlxwxcb.cn/news/detail-464315.html
- 緩存擊穿:先擊后穿
- 緩存擊穿的解決方案有:設(shè)置熱點(diǎn)數(shù)據(jù)永不過期、定時(shí)更新、分布式
- 緩存穿透:將緩存穿了個(gè)洞
- 緩存穿透的解決方案有:業(yè)務(wù)層校驗(yàn)、緩存空值、布隆過濾器
- 緩存雪崩:大量失效Key
- 緩存雪崩的解決方案有:設(shè)置不同的過期時(shí)間、緩存預(yù)熱、多級(jí)緩存、限流熔斷、集群和負(fù)載均衡
到了這里,關(guān)于緩存擊穿、穿透、雪崩及常用解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!