緩存系列:緩存雪崩的解決思路
大家好,我是華仔。
上次我們討論了在分布式系統下的緩存架構體系,從瀏覽器緩存到客戶端緩存,再到CDN緩存,再到反向代理緩存,再到本地緩存,再到分布式緩存。整個鏈路中有非常多的緩存。
在整個緩存鏈路,存在各種各樣的問題,常見的問題有緩存穿透、緩存擊穿、緩存雪崩、緩存數據一致性問題等。不常見的問題有緩存傾斜、緩存阻塞、緩存慢查詢、緩存主從一致性問題、緩存高可用、緩存故障發現與故障恢復、集群擴容收縮、大Key熱Key等等。
今天我們就來聊聊:緩存雪崩
緩存雪崩,顧名思義,是緩存崩了。如果這樣理解的話,那就錯了,請跟我來一探究竟吧。
老規矩,先看一下本文大綱:
- 什么是緩存雪崩
- 緩存雪崩的痛點有哪些
- 緩存雪崩的解決思路
- 總結
什么是緩存雪崩
我們知道,緩存的工作原理是先從緩存中獲取數據,如果有數據則直接返回給用戶,如果沒有數據則從慢速設備上讀取實際數據并且將數據放入緩存。就像這樣:
緩存里面的數據有很多,如果有一個key過期,那么就需要回溯查詢,如果這個key是熱點key,慢設備壓力劇增,有可能導致慢設備宕機。就像這樣:
這便是我們之前說的:緩存擊穿
那如果是很多key都過期了,那請求都會透過緩存層,直奔慢設備了,如果這些失效的key的請求之和很大,那么慢設備壓力劇增,有可能導致慢設備宕機。就像這樣:
這便是我們今天的主題:緩存雪崩
沒錯,從上面的含義其實已經能夠理解出一個區別:
緩存擊穿強調單Key過期+高并發;
緩存雪崩強調多key過期+高并發。
(所以,緩存雪崩不是緩存崩了,是一大片大片的緩存數據都在同一時間都失效了)
雪崩,實在是太可怕了。
緩存雪崩的痛點有哪些
- 熱點數據扎堆過期
- 緩存層瞬間透明化
- 慢設備層有被擊垮的風險
大家猜想一下,為什么會瞬間有大量數據過期呢?
有兩個方向,其一是大量數據同時放入緩存+過期時間設置的時間是一致的;其二是大量數據放入緩存的時間點不一樣,但是過期時間是同一時間過期。
其一比較好理解,給大家舉幾個場景就更好了理解了,比如系統在啟動的時候或者每天定時的對大量數據進行預熱,并且過期時間是一樣的。又或者是大促,商品在同一時刻開放,大量的用戶進行不同商品的訪問,這些商品數據幾乎同時進入緩存,并且過期時間是一樣的。
其二不太容易理解,給大家舉個場景就好了。比如有一個給用戶推送消息的需求,但是一天只允許推送一次,假設給張三同學早上8點推送,那么可以將這條數據放入緩存,過期時間為16小時,再次給張三推送的時候檢查緩存是否存在,緩存存在則不允許推送了,緩存不存在則允許推送。給李四同學下午14點推送了一條消息,那么給李四同學放緩存的數據過期時間應該是10小時。這個場景就解釋了在不同的時間點放入的數據,它們的過期時間不一樣,但是都是在同一時刻過期(在這個例子中是每天0點過期)。
緩存雪崩的解決思路
1、從上述的其一來看,是數據放入緩存的時間和過期時間一樣,所以最終大量數據同一時間過期。
所以,我們從這一點來看,我們可以改變數據放入緩存的的時間,也可以選擇修改數據的過期時間,讓過期時間不一致,最終的目的是讓數據分散在不同的時間點過期,從而減少數據庫的高并發壓力。很顯然,修改數據的過期時間更簡單一些,讓緩存時間在一定的區域隨機取值,很輕松就能解決了一個緩存雪崩的問題。
2、當然了,問題的產生是數據過期了,所以還有一種解決方案是:讓你的數據永不過期!顯然,你的leader或者身為leader的你是不會這么玩的,這個方案基本不可行。原因是就算讓緩存數據在緩存永不過期,那難道緩存敢保證100%保證可用嗎?不敢,所以,你還是需要準備planB,做好緩存宕機或者緩存數據不存在的備案。
3、既然是因為并發訪問導致,我們是不是可以由高并發轉換低并發,稱之為互斥鎖,或者分布式鎖等,總之,加鎖來保證高并發轉換成低并發。
4、我們繼續分析,像這種熱點數據,是不是應該由熱點服務器去完成,對吧?我們應該去做隔離機制,如果你有一套實時熱點發現系統,再加上熱點流量自動遷移到熱點服務器,就算有這些有什么用,能解決問題嗎?答案是不能,因為熱點服務器仍然是需要防止緩存雪崩的,方案在上面已經提到過了就不再贅述了。這里只是拋磚引玉,淺談環境隔離與實時熱點發現。
5、繼續,既然是數據庫承受不住了,我們在知道問題的情況下,可以對數據做離散分布,讓它均勻地分布在我們的分布式數據庫中,同時對數據庫盡量的水平擴容,常見的分庫分表策略有32庫32表,64庫64表,128庫128表......,這樣做的目的是讓單臺數據庫壓力變小,從而防止緩存雪崩。
6、繼續分析,我們從現象來看,是數據庫宕機了,原因是數據庫接受到的瞬間請求太多了,數據庫扛不住壓力所以就停止工作了。那我們是不是可以這么分析,如果我們提前知道數據庫能承受的最大閾值是多少,并且提前設置好數據庫的閾值或者服務的閾值,如果瞬間流量來了,我們把超過閾值的流量進行排隊等待或者直接拒絕服務,保證數據庫的壓力是不超過閾值的,是不是也能解決緩存雪崩所帶來的影響呢?
那么這里面有涉及到幾個數據:數據庫的閾值從何得知、服務的閾值從何得知、如何設置數據庫或者服務的閾值。
答案是:數據的閾值應該是壓測后得出,而設置閾值應該是在網關層進行限流處理,所以你需要有這樣的限流平臺。
對于壓測和網關,我們后續會有專門的文章來討論,本期暫且不深入了,敬請期待。可以關注我的公中號:李哥技術
總結
其實緩存雪崩的理解很簡單,為什么說得這么復雜,原因很簡單,就是不想讓大家用背八股文一樣的方式去記憶,而是靠深入理解它的痛點然后逐步分析解決方案去記憶。
來總結一下吧。
概念:緩存雪崩指的是大片大片的緩存數據同時過期失效,再加上高并發的請求進入到慢設備,慢設備壓力劇增,有可能導致慢設備宕機,這便是緩存雪崩。
解決方案:
- 修改數據放入緩存的時間,或修改數據在緩存中的過期時間;
- 讓緩存數據永不過期;
- 互斥鎖,由高并發轉換成低并發,保護DB;
- 熱點隔離,實時熱點發現系統;
- 水平擴容數據庫,壓力平攤,保護DB;
- 提前壓測,得出閾值,限流處理,保護服務與DB;
好了,本期緩存雪崩的解決思路就到這里了,感謝閱讀!