Redis 的“熱點 key”問題指的是某些 key 被頻繁訪問(讀或寫),導致服務器負載不均衡甚至性能瓶頸。在高併發系統中,這是常見的性能隱患之一。
一、熱點 Key 的危害
- 單點瓶頸:某個 key 被高頻訪問,導致 Redis CPU 飆升,QPS 降低。
- 緩存擊穿:熱點 key 失效後瞬間大量請求落到數據庫,可能造成雪崩。
- 負載不均:集羣中某節點因為熱點 key 負載過高。
- 延遲上升:影響整體服務響應時間,拖慢其他正常請求。
二、熱點 Key 的識別方法
1. 使用 Redis 命令定位熱點 Key:
MONITOR(開發/測試環境用):實時查看請求命令redis-cli --hotkeys:採樣找出熱點 key(Redis 4.0+)slowlog get:分析慢查詢的 keyinfo commandstats:查看命令訪問頻率- Redis 集羣環境可結合 proxy(如 Twemproxy)或分析訪問日誌
三、熱點 Key 的治理策略
✅ 1. 緩存預熱(預加載)
熱點 key 在高峯期前主動設置好緩存,避免冷啓動時併發打穿數據庫。
# 啓動前或定時腳本預熱
SET user:10086 {...} EX 3600
✅ 2. 使用多級緩存(本地 + Redis)
減少熱點 key 對 Redis 的壓力,典型方案:
- 本地緩存(如 Guava、Caffeine、LruCache)
- 分佈式緩存(Redis)
// 示例偽代碼
if (localCache.contains(key)) return localCache.get(key);
val = redis.get(key);
localCache.put(key, val);
✅ 3. 熱點 Key 拆分(哈希打散)
將一個 key 拆成多個 key,降低單點訪問壓力。
- 例:將
hotkey拆為hotkey_1\~hotkey_10,客户端隨機訪問或輪詢
SET hotkey_1 "val"
SET hotkey_2 "val"
...
GET hotkey_${random(1,10)}
✅ 4. 異步更新 + 延遲雙刪
保證熱點 key 一致性但減小 Redis 壓力:
更新 DB 後:
1. 刪除 Redis key
2. 異步通知更新業務邏輯
3. 延遲再次刪除 key(避免併發寫入後被舊數據覆蓋)
✅ 5. 加鎖防擊穿
針對失效的熱點 key,可使用互斥鎖(如 Redis 的分佈式鎖)防止併發回源:
-- 獲取鎖
SETNX lock:key true
-- 設置過期
EXPIRE lock:key 3
-- 查詢 DB & set 緩存
-- 刪除鎖
DEL lock:key
可使用 Redisson、ZooKeeper 等實現分佈式鎖。
✅ 6. 合理設置過期時間(TTL)
防止多個熱點 key 同時過期,觸發併發回源:
- 使用隨機 TTL 避免“緩存雪崩”
expire = 3600 + random.randint(0, 300)
redis.set('key', val, ex=expire)
✅ 7. 請求限流
對訪問頻率過高的 key 設置限流策略,保護後端服務:
- 應用層限流(如 Guava RateLimiter)
- Redis 令牌桶 / 計數器實現限流
✅ 8. 數據分片 / 分佈式部署
- 將 Redis 集羣分區部署,熱點數據分佈到不同實例
- 使用 proxy 分流請求(如 Codis、Twemproxy)
四、治理最佳實踐總結
| 手段 | 應用場景 | 優勢 | 注意事項 |
|---|---|---|---|
| 本地緩存 | 熱點讀 | 減輕 Redis 壓力 | 一致性問題 |
| Key 拆分 | 熱點 key 寫多 | 分攤負載 | 編碼複雜度 |
| 緩存預熱 | 高併發初期 | 避免擊穿 | 需計劃 |
| 分佈式鎖 | 緩存失效 | 防擊穿 | 增加延遲 |
| 延遲雙刪 | DB寫操作 | 保證一致性 | 需時機把握好 |