有些 Redis 的快取資料會設定 TTL 來讓它自然的過期,但如果這種會過期的快取資料多,而過期的時間又都非常接近,就很有機會中所謂的「雪崩」。
雪崩發生時候,最先有感的就是 Redis server 自己本身的 cpu & expire 數量會瞬間飆高。
這會間接的影響到,接下來打進來的 request 處理速度。如果 cpu 持續飆高不下,redis server 的 connection 數就會跟著越來越高。
然後程式層的部份,開始有 request queue 住的現象,吃的量會瞬間往下掉。
假設這一大批 expire 的 key 都是一些熱資料,這也會導致後端的資料庫壓力直接變大。
這基本上算是一連串的炸彈,畢竟一個單點開始卡住,跟它有關的後續操作都會開始被影響到。
但最根本的原因還是 Redis 大量 key expire 開始,Redis 為了要刪除這些過期的資料,會不斷的需要 cpu 資源來處理,所以 cpu 就會飆高。
Redis cpu 一飆高,接下來再打進來的請求,處理速度就會被拖慢。這個點開始慢的時候,源頭打進來的程式端就會跟著慢。
而 Redis 裡面的快取資料都沒了,變成會一路打到後端資料庫去。
這一連串的慢,就看哪一個點會最先撐不住,而導致服務中斷了。
服務在 peak time 的時候請求本來就會比較多,如果在實作上也是快取沒資料就從後端資料庫補的話,那這時候很有機會會寫入一批 TTL 時間道接近的資料進到 Redis 內。
某一個功能或服務掛 maintainance,在恢復運作的時候,也是瞬間請求開始進來。這時候 Redis 裡面幾乎都是空的,也是導致補了很多 TTL 時間相近的資料進去。
服務剛起起來,正在進行批次作業將大量資料寫入 Redis(就是所謂的預熱)。這樣的動作也是會寫入很多 TTL 時間相近的資料進去。
簡單粗爆但好用的解法,就是在設定 TTL 的時候,除了原本的固定值之外,再額外加上一個隨機秒數。
這個秒數可以視情況來調整(快取的數量),比如說 60 ~ 600 秒都可以。
因為核心的概念只有一個,就是讓他們在過期的時候,可以把時間打散即可。
這樣就不會在過期的時候,因為同時的量過多,而導致 redis cpu 飆高。