緩存擊穿:
目前涉及到大并發(fā)訪問時黄绩,一般我們會使用Redis之類的緩存服務(wù),以提高訪問效率魄缚,降低對數(shù)據(jù)庫的壓力正常的使用場景為:
1宝与、請求到來->訪問Redis->有值拿到值返回焚廊,
2、請求到來->訪問Redis->無值->查詢數(shù)據(jù)庫->有值更新redis
3习劫、請求到來->訪問Redis->無值->查詢數(shù)據(jù)庫->無值空返回
當(dāng)redis無值咆瘟、數(shù)據(jù)庫也無值的時候,并發(fā)量大的時候诽里,會出現(xiàn)大量請求的壓力壓到數(shù)據(jù)庫袒餐,導(dǎo)致數(shù)據(jù)庫響應(yīng)變慢甚至崩潰,我們稱之為緩存擊穿谤狡。
解決方案:
對于一些設(shè)置了過期時間的key灸眼,如果這些key可能會在某些時間點被超高并發(fā)地訪問,是一種非衬苟“熱點”的數(shù)據(jù)焰宣。這個時候,需要考慮一個問題:緩存被“擊穿”的問題捕仔,這個和緩存雪崩的區(qū)別在于這里針對某一key緩存匕积,前者則是很多key。
緩存在某個時間點過期的時候榜跌,恰好在這個時間點對這個Key有大量的并發(fā)請求過來闪唆,這些請求發(fā)現(xiàn)緩存過期一般都會從后端DB加載數(shù)據(jù)并回設(shè)到緩存,這個時候大并發(fā)的請求可能會瞬間把后端DB壓垮钓葫。
緩存穿透:
緩存穿透是指查詢一個一定不存在的數(shù)據(jù)悄蕾,由于緩存是不命中時被動寫的,并且出于容錯考慮础浮,如果從存儲層查不到數(shù)據(jù)則不寫入緩存帆调,這將導(dǎo)致這個不存在的數(shù)據(jù)每次請求都要到存儲層去查詢,失去了緩存的意義霸旗。在流量大時贷帮,可能DB就掛掉了戚揭,要是有人利用不存在的key頻繁攻擊我們的應(yīng)用诱告,這就是漏洞。
解決方案:
有很多種方法可以有效地解決緩存穿透問題民晒,最常見的則是采用布隆過濾器精居,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被 這個bitmap攔截掉潜必,從而避免了對底層存儲系統(tǒng)的查詢壓力靴姿。另外也有一個更為簡單粗暴的方法(我們采用的就是這種),如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在磁滚,還是系統(tǒng)故障)佛吓,我們?nèi)匀话堰@個空結(jié)果進(jìn)行緩存宵晚,但它的過期時間會很短,最長不超過五分鐘
緩存雪崩:
緩存雪崩是指在我們設(shè)置緩存時采用了相同的過期時間维雇,導(dǎo)致緩存在某一時刻同時失效淤刃,請求全部轉(zhuǎn)發(fā)到DB,DB瞬時壓力過重雪崩吱型。
解決方案:
緩存失效時的雪崩效應(yīng)對底層系統(tǒng)的沖擊非骋菁郑可怕。大多數(shù)系統(tǒng)設(shè)計者考慮用加鎖或者隊列的方式保證緩存的單線 程(進(jìn)程)寫津滞,從而避免失效時大量的并發(fā)請求落到底層存儲系統(tǒng)上铝侵。這里分享一個簡單方案就時講緩存失效時間分散開,比如我們可以在原有的失效時間基礎(chǔ)上增加一個隨機(jī)值触徐,比如1-5分鐘隨機(jī)咪鲜,這樣每一個緩存的過期時間的重復(fù)率就會降低,就很難引發(fā)集體失效的事件撞鹉。