關(guān)于緩存,每個(gè)開發(fā)人員都應(yīng)該知道的三個(gè)問題
?前言
雖然緩存被認(rèn)為是軟件系統(tǒng)的性能助推器,但如果處理不當(dāng),它也容易出現(xiàn)錯(cuò)誤。 在本文中,我將介紹 3 個(gè)有時(shí)可能會造成災(zāi)難性后果的常見緩存問題,希望大家在架構(gòu)上引入緩存時(shí),需要考慮到。
緩存擊穿
緩存故障 當(dāng)緩存鍵過期時(shí)會發(fā)生緩存故障,并且多個(gè)請求同時(shí)訪問數(shù)據(jù)庫以查找相同的鍵。 讓我們來看看它是如何工作的:
- 熱緩存鍵過期。
- 多個(gè)并發(fā)請求進(jìn)來搜索同一個(gè)鍵。
- 服務(wù)器向數(shù)據(jù)庫發(fā)起多個(gè)并發(fā)請求以查找相同的鍵。
緩存擊穿會顯著增加數(shù)據(jù)庫的負(fù)載,尤其是當(dāng)許多熱鍵同時(shí)過期時(shí)。 下面是解決這個(gè)問題的2種解決方案:
- 獲取搜索到的key的分布式鎖,當(dāng)一個(gè)線程試圖更新緩存時(shí),其他線程需要等待。
- 利用Refresh-ahead 策略異步刷新熱數(shù)據(jù),使熱鍵永不過期。
緩存穿透
緩存穿透 當(dāng)搜索到的key?既不在緩存中, 也不在數(shù)據(jù)庫中時(shí),就會發(fā)生**緩存穿透,**連數(shù)據(jù)庫都穿透過去了。 讓我們來看看它是如何工作的,當(dāng)key既不在緩存中也不在數(shù)據(jù)庫中時(shí),就會發(fā)生這種情況。
- 當(dāng)用戶查詢key時(shí),應(yīng)用程序由于緩存未命中而去查詢數(shù)據(jù)庫數(shù)據(jù)庫。
- 由于數(shù)據(jù)庫不包含該key并返回空結(jié)果,因此該key也不會被緩存。
- 因此,每個(gè)查詢最終都會導(dǎo)致緩存未命中,而命中數(shù)據(jù)庫,直接進(jìn)行查庫。
雖然乍一看這似乎微不足道,但攻擊者可以通過使用此類密鑰啟動大量搜索來嘗試破壞你的數(shù)據(jù)庫。 為了解決這個(gè)問題,我們可以:
- 緩存過期時(shí)間較短的空結(jié)果。
- 使用布隆過濾器。在查詢數(shù)據(jù)庫之前,應(yīng)用程序在布隆過濾器中查找key,如果key不存在則立即返回。
緩存雪崩
當(dāng)對數(shù)據(jù)庫的請求突然激增時(shí),就會發(fā)生緩存雪崩。 這發(fā)生在:
- 許多緩存數(shù)據(jù)同時(shí)過期。
- 緩存服務(wù)宕機(jī),所有請求都直接訪問數(shù)據(jù)庫。
數(shù)據(jù)庫流量的突然激增可能會導(dǎo)致級聯(lián)效應(yīng),并可能最終導(dǎo)致您的服務(wù)崩潰。 下面是一些常見的解決方案:
- 調(diào)整緩存鍵的過期時(shí)間,使它們不會同時(shí)過期。
- 使用Refresh-ahead 策略異步刷新熱數(shù)據(jù),使其永不過期。
- 使用緩存集群來避免單點(diǎn)故障。當(dāng)主節(jié)點(diǎn)崩潰時(shí),其中一個(gè)副本被提升為新的主節(jié)點(diǎn)。
總結(jié)
雖然這些緩存問題起初看起來微不足道,但有時(shí)可能會對我們的下游客戶端和依賴項(xiàng)產(chǎn)生級聯(lián)效應(yīng)。事先了解它們可以讓我們設(shè)計(jì)一個(gè)更強(qiáng)大的系統(tǒng),也可以簡化我們的故障排除過程。