面試被吊打系列-Redis緩存血崩
本文轉(zhuǎn)載自微信公眾號(hào)「JAVA日知錄」,作者單一色調(diào)。轉(zhuǎn)載本文請(qǐng)聯(lián)系JAVA日知錄公眾號(hào)。
小張興沖沖去面試,結(jié)果因?yàn)閞edis的緩存雪崩問題被面試官拒絕!
小張:面試官,你好。我是來參加面試的。
面試官:你好,小張。我看了你的簡(jiǎn)歷,你們平時(shí)在項(xiàng)目中用了redis,能說一下你們使用redis的場(chǎng)景嗎?
小張:redis的話我們主要是用來存儲(chǔ)一些常用的配置類數(shù)據(jù)還有一些熱點(diǎn)數(shù)據(jù);還有存儲(chǔ)一些到期失效的數(shù)據(jù),比如登錄用戶頒發(fā)的token等。
面試官:那好,既然你們用來存儲(chǔ)熱點(diǎn)數(shù)據(jù)。那么我來問你個(gè)實(shí)際場(chǎng)景,「查詢熱點(diǎn)數(shù)據(jù)的時(shí)候會(huì)先從緩存加載,如果緩存沒有命中則會(huì)檢索數(shù)據(jù)庫獲取數(shù)據(jù)。往往我們還會(huì)給熱點(diǎn)緩存數(shù)據(jù)設(shè)置一個(gè)過期時(shí)間。那么我的問題是,假設(shè)在某一時(shí)間點(diǎn)熱點(diǎn)緩存全部過期失效了,這樣所有的請(qǐng)求都會(huì)直接進(jìn)入數(shù)據(jù)庫,一瞬間就會(huì)把數(shù)據(jù)庫壓垮,如果是你會(huì)怎么解決這個(gè)問題?」
小張:emm...面試官,我肚子有點(diǎn)不舒服,我先回去了。小張卒!
面試官:因?yàn)榫彺嫱粫r(shí)間大面積的失效,或者緩存服務(wù)暫時(shí)不能提供服務(wù)等,從而導(dǎo)致所有請(qǐng)求都去查數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫CPU和內(nèi)存負(fù)載過高,甚至宕機(jī)。這一現(xiàn)象被稱之為 「緩存雪崩」。
緩存血崩可以通過以下四個(gè)維度來解決:
「緩存預(yù)熱」
數(shù)據(jù)加熱的含義就是在正式部署之前,先把可能的數(shù)據(jù)先預(yù)先訪問一遍,這樣部分可能大量訪問的數(shù)據(jù)就會(huì)加載到緩存中。在即將發(fā)生大并發(fā)訪問前手動(dòng)觸發(fā)加載緩存不同的key。
「加上互斥鎖」
可以在第一個(gè)查詢數(shù)據(jù)的請(qǐng)求上使用一個(gè)互斥鎖來鎖住它,其他的線程走到這一步拿不到鎖就等著,等第一個(gè)線程查詢到了數(shù)據(jù),然后將數(shù)據(jù)放到redis緩存起來。后面的線程進(jìn)來發(fā)現(xiàn)已經(jīng)有緩存了,就直接走緩存。
「過期時(shí)間均勻分布」
給緩存的時(shí)效時(shí)間加上隨機(jī)因子,即給緩存設(shè)置不同的過期時(shí)間,讓緩存失效的時(shí)間點(diǎn)盡量均勻。
「構(gòu)建高可用的緩存系統(tǒng)」
把Redis設(shè)計(jì)成高可用的,即使個(gè)別節(jié)點(diǎn)、個(gè)別機(jī)器、甚至是機(jī)房宕掉,依然可以提供服務(wù),例如 Redis Sentinel 和 Redis Cluster 都實(shí)現(xiàn)了高可用。
面試官:各位看官朋友們,你們學(xué)會(huì)怎么解決緩存雪崩的問題了嗎?希望你們以后面試不會(huì)被這個(gè)問題難倒喲~
小張:學(xué)到了學(xué)到了,我下次再來。(早知道不提什么熱點(diǎn)數(shù)據(jù)了,不提面試官就不會(huì)問。)
面試官:小樣,不問這個(gè)那么我不會(huì)問其他的了嗎?你下次再來試試!