緩存穿透
緩存穿透是指查詢一個緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù)笙瑟,由于大部分緩存策略是被動加載的亮钦,并且出于容錯考慮盏求,如果從存儲層查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個不存在的數(shù)據(jù)每次請求都要到存儲層去查詢宵喂,失去了緩存的意義糠赦。用戶不斷發(fā)起請求,在流量大時,就可能對DB形成巨大的壓力拙泽,利用不存在的key頻繁攻擊應(yīng)用也是很大的問題淌山。
解決方案:
1.緩存和數(shù)據(jù)庫中都不存在的數(shù)據(jù),可以將此key對應(yīng)的value設(shè)置為一個默認的值顾瞻,比如“NULL”泼疑,并設(shè)置一個緩存的失效時間,這時在緩存失效之前荷荤,所有通過此key的訪問都被緩存擋住了退渗。后面如果此key對應(yīng)的數(shù)據(jù)在DB中存在時,緩存失效之后蕴纳,通過此key再去訪問數(shù)據(jù)会油,就能拿到新的value了。
2.接口層增加校驗古毛,比如用戶鑒權(quán)校驗翻翩,id根據(jù)數(shù)據(jù)場景做基礎(chǔ)校驗,id<=0的直接攔截稻薇。
3.布隆過濾器
關(guān)于布隆過濾器嫂冻,后面會詳細介紹。布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu)塞椎,利用極小的內(nèi)存桨仿,可以判斷大量的數(shù)據(jù)“一定不存在或者可能存在”。
對于緩存穿透忱屑,我們可以將查詢的數(shù)據(jù)條件都哈希到一個足夠大的布隆過濾器中蹬敲,用戶發(fā)送的請求會先被布隆過濾器攔截暇昂,一定不存在的數(shù)據(jù)就直接攔截返回了莺戒,從而避免下一步對數(shù)據(jù)庫的壓力。
緩存擊穿
緩存擊穿是指緩存中的一個熱點Key(比如一個秒殺商品)急波,在某個時間點過期的時候从铲,恰好在這個時間點訪問量劇增,對這個Key有大量的并發(fā)請求過來澄暮,請求發(fā)現(xiàn)緩存過期一般都會從后端DB加載數(shù)據(jù)并回設(shè)回緩存名段,但就在緩存中的數(shù)據(jù)還沒有完全從DB中加載過來的這個時間段期間,并發(fā)瞬間造成大量請求直接擊穿到DB泣懊,對DB形成巨大壓力伸辟。緩存擊穿,又叫熱點key問題馍刮,是這三個問題中最經(jīng)典的一個問題信夫。
解決方案:
1.設(shè)置熱點數(shù)據(jù)永不過期
對于某個需要頻繁獲取的信息,緩存在Redis中,并設(shè)置其永不過期静稻。當然這種方式比較粗暴警没,對于某些業(yè)務(wù)場景是不適合的。
2.定時更新
比如這個熱點數(shù)據(jù)的過期時間是1h振湾,那么每到59minutes時杀迹,通過定時任務(wù)去更新這個熱點key,并重新設(shè)置其過期時間押搪。
3.互斥鎖
這是解決緩存擊穿比較常用的方法树酪。
互斥鎖簡單來說就是在Redis中根據(jù)key獲得的value值為空時,先鎖上嵌言,然后從數(shù)據(jù)庫加載嗅回,加載完畢,釋放鎖摧茴。若其他線程也在請求該key時绵载,發(fā)現(xiàn)獲取鎖失敗,則睡眠一段時間(比如100ms)后重試苛白。
緩存雪崩
緩存雪崩娃豹,是指緩存中設(shè)置了大批量相同過期時間的數(shù)據(jù)同時過期失效,而在這一刻訪問量劇增购裙,緩存近乎失效懂版,所有請求全部轉(zhuǎn)向DB,DB瞬時壓力過重雪崩躏率,甚至down機躯畴。和緩存擊穿不同的是,緩存擊穿指并發(fā)查同一條數(shù)據(jù)薇芝,緩存雪崩是不同數(shù)據(jù)都過期了蓬抄,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫。
解決方案:
1.設(shè)置有效期均勻分布
避免緩存設(shè)置相近的有效期夯到,我們可以在設(shè)置有效期時增加隨機值,或者統(tǒng)一規(guī)劃有效期嚷缭,使得過期時間均勻分布。
2.數(shù)據(jù)預(yù)熱
對于即將來臨的大量請求耍贾,我們可以提前走一遍系統(tǒng)阅爽,將數(shù)據(jù)提前緩存在Redis中,并設(shè)置不同的過期時間荐开。
3.保證Redis服務(wù)高可用
前面我們介紹過Redis的哨兵模式和集群模式付翁,為防止Redis集群單節(jié)點故障,可以通過這兩種模式實現(xiàn)高可用晃听。