一、先給緩存雪崩定個性:啥是 Redis 緩存雪崩?
二、為啥會發生緩存雪崩?(兩大核心原因)
- 人為設置了統一的過期時間:比如做活動時,給所有活動商品緩存設了 2 小時過期,2 小時後緩存全失效;
- 緩存 Key 的過期時間 “扎堆”:比如用時間戳 + 固定時長設置過期,導致大量 Key 在同一時間段過期。
- Redis 集羣宕機(比如服務器斷電、網絡故障、Redis 進程崩潰);
- 突發流量打垮 Redis(比如秒殺活動,請求量遠超 Redis 處理能力)。
三、怎麼解決緩存雪崩?(從易到難,新手也能落地)
1. 先解決 “緩存批量失效” 的問題
- 過期時間加隨機值(最簡單有效)給每個 Key 的過期時間都加一個隨機數,避免 “扎堆失效”。比如原本要設 2 小時過期,就改成 “2 小時 ± 10 分鐘”,讓緩存失效時間分散開。代碼示例(Java):
java運行
// 原過期時間:7200秒(2小時)
int baseExpire = 7200;
// 隨機加0-600秒(10分鐘)
int randomExpire = new Random().nextInt(600);
// 最終過期時間:7200~7800秒
redisTemplate.opsForValue().set("goods:1001", goodsInfo, baseExpire + randomExpire, TimeUnit.SECONDS);
- 核心數據永不過期對系統核心、訪問量極高的數據(比如首頁輪播圖、熱門商品),不設置過期時間,由程序手動更新緩存(比如商品價格變了,再更新緩存),避免這些數據失效。
2. 解決 “Redis 掛了” 的問題
- Redis 集羣化部署(高可用)不要只部署一台 Redis,用主從複製 + 哨兵模式,或者 Redis Cluster 集羣。就算一台 Redis 掛了,其他節點能立刻頂上,不會導致緩存服務整體不可用。
- 添加緩存降級 / 熔斷機制當 Redis 掛了,不是直接把所有請求丟給數據庫,而是做 “降級處理”:
- 比如返回兜底數據(“當前系統繁忙,請稍後再試”);
- 用熔斷器(比如 Sentinel)限制訪問數據庫的請求量,避免數據庫被沖垮。
3. 終極兜底:保護數據庫
- 數據庫加讀寫分離 / 分庫分表:提升數據庫本身的抗壓力;
- 加分佈式鎖 / 限流:限制同一時間訪問數據庫的請求數,比如用 Guava 的 RateLimiter 做接口限流;
- 開啓緩存預熱:在流量高峯前(比如秒殺開始前),提前把熱點數據加載到緩存裏,避免高峯時緩存為空。
四、緩存雪崩 vs 緩存擊穿 vs 緩存穿透(新手別搞混)
|
問題
|
核心場景
|
影響範圍
|
|
緩存雪崩
|
大量緩存同時失效 / Redis 掛了
|
整個系統(數據庫崩潰)
|
|
緩存擊穿
|
單個熱點 Key 失效(比如秒殺商品)
|
單個 Key 對應的數據庫請求
|
|
緩存穿透
|
請求不存在的 Key(比如查 ID=-1 的商品)
|
直接穿透緩存到數據庫
|