3. 热点Key识别与监控

热点Key(Hot Key)是指在一段时间内被大量并发访问的Redis Key。当热点Key的QPS超过单节点处理能力时,会导致Redis实例CPU飙升、请求超时甚至雪崩。本章聚焦于四种主流识别手段:Monitor命令、Slow Log、Big Keys扫描以及客户端统计,并给出生产环境下的组合策略。

核心原则:热点识别应作为常态化监控任务,而非事后救火手段。建议将识别周期控制在分钟级,并联动告警系统自动触发削峰策略。

3.1 四种识别手段对比

手段 原理 优点 缺点 适用场景
MONITOR 实时打印所有命令 全量可见,精准定位Key 高并发下性能损耗大,可能撑爆输出缓冲区 临时排查、低流量环境
SLOWLOG 记录执行时间超阈值的命令 低开销,自动记录 仅反映慢查询,不直接反映高频访问 识别大Key或复杂命令导致的延迟
BIGKEYS 扫描并统计大Key分布 直接定位大Key,辅助分析热点成因 扫描期间可能阻塞,需避开高峰期 大Key导致的热点问题
客户端统计 在SDK侧统计Key访问频次 零侵入,无性能损耗,可定制化 需改造客户端代码,多语言维护成本 生产环境长期监控

3.2 MONITOR 命令实战

MONITOR 会实时输出Redis处理的所有命令,适合临时抓取热点Key。但务必注意:生产环境开启MONITOR会使Redis吞吐量下降50%以上,建议仅在低峰期或从节点执行。

# 在redis-cli中开启MONITOR
redis 127.0.0.1:6379> MONITOR
OK
# 输出示例(实时流)
1627989123.456789 [0 10.0.0.1:54321] "GET" "product:1001"
1627989123.456890 [0 10.0.0.2:54322] "GET" "product:1001"
1627989123.456912 [0 10.0.0.3:54323] "GET" "product:1002"
...

通过管道将输出重定向到文件,再用脚本统计Key出现频率:

# 采集30秒后统计Top 10热点Key
timeout 30 redis-cli MONITOR > monitor.log
awk '{for(i=5;i<=NF;i++) if($i ~ /^"[A-Z]+"/) print $i}' monitor.log \
  | sort | uniq -c | sort -rn | head -10
⚠️ 生产警告:MONITOR 会持续占用输出缓冲区,长时间运行可能导致客户端与Redis连接断开。建议单次采集不超过60秒,且优先在只读副本上执行。

3.3 SLOWLOG 与 BIGKEYS 辅助分析

SLOWLOG 虽然不直接反映热点,但热点Key往往伴随高延迟。配置慢查询阈值后,定期检查慢日志可间接发现异常Key。

# 设置慢查询阈值为10毫秒,最多保留128条
CONFIG SET slowlog-log-slower-than 10000
CONFIG SET slowlog-max-len 128

# 查看最近10条慢查询
SLOWLOG GET 10

# 输出示例
1) 1) (integer) 14          # 唯一ID
   2) (integer) 1627989123  # 时间戳
   3) (integer) 12000       # 执行耗时(微秒)
   4) 1) "HGETALL"          # 命令
      2) "user:profile:9527" # Key
   5) "127.0.0.1:6379"

BIGKEYS 扫描使用 --bigkeys 参数,会遍历所有Key并统计每种数据结构的最大Key:

# 执行大Key扫描(建议在从节点或低峰期执行)
redis-cli --bigkeys

# 输出片段
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec...
[00.00%] Biggest string found so far '"session:token:abc123"' with 2048 bytes
[12.50%] Biggest list  found so far '"queue:order"' with 15000 items
...
💡 最佳实践:将SLOWLOG与BIGKEYS结合使用——先通过SLOWLOG发现异常延迟的Key,再针对性地用BIGKEYS确认该Key是否为大Key,从而判断热点是否由数据量过大引起。

3.4 客户端统计方案(推荐)

客户端统计是生产环境最推荐的方案,通过在SDK层嵌入计数器,零侵入地统计每个Key的访问频次。以Java的Jedis为例,可借助本地缓存(如Caffeine)实现滑动窗口统计:

// 伪代码:客户端热点统计
public class HotKeyMonitor {
    // 滑动窗口:每分钟统计一次,窗口大小60秒
    private Cache<String, AtomicLong> counter = Caffeine.newBuilder()
            .expireAfterWrite(60, TimeUnit.SECONDS)
            .build();

    public void recordAccess(String key) {
        AtomicLong count = counter.get(key, k -> new AtomicLong(0));
        long current = count.incrementAndGet();
        // 阈值判断:单Key QPS > 1000 触发告警
        if (current > 1000) {
            alert("Hot key detected: " + key + ", QPS: " + current);
        }
    }

    // 在Jedis调用处埋点
    public String get(String key) {
        recordAccess(key);
        return jedis.get(key);
    }
}

其他语言的客户端统计思路类似:

  • Python (redis-py):使用装饰器或中间件拦截命令调用,利用 collections.Counter 做频次统计。
  • Go (go-redis):通过 Hook 接口实现命令拦截,统计Key访问次数。
  • Node.js (ioredis):在 sendCommand 方法中注入计数器。

3.5 热点识别架构图

下图展示了四种识别手段在监控体系中的协作关系:

热点Key识别与监控架构 热点Key识别与监控架构 Redis 实例(主/从) MONITOR 实时命令流 SLOWLOG 慢查询日志 BIGKEYS 大Key扫描 客户端统计 SDK计数器 热点分析引擎 频次统计 · 滑动窗口 · 阈值判定 告警通知 钉钉/邮件/短信 热点Key列表 Top N 持久化 推荐组合:客户端统计(长期) + MONITOR(临时抓取) + SLOWLOG/BIGKEYS(辅助定位)

3.6 生产环境组合策略

单一手段无法覆盖所有场景,建议按以下优先级组合:

  1. 第一道防线(客户端统计):在所有业务SDK中嵌入计数器,实时上报QPS超过阈值的Key。这是零损耗、最精准的方案。
  2. 第二道防线(SLOWLOG + BIGKEYS):每5分钟拉取慢查询日志,每30分钟在从节点执行大Key扫描,发现潜在热点。
  3. 第三道防线(MONITOR应急):当告警触发但客户端统计未捕获时,在从节点临时开启MONITOR 30秒,抓取全量命令进行离线分析。
💡 阈值参考:单Key QPS > 5000 或 单Key占用内存 > 10MB 应触发告警。具体阈值需根据实例规格(如8核16GB)和业务容忍度调整。

3.7 避坑指南

常见错误 后果 正确做法
在主节点执行BIGKEYS扫描 阻塞主线程,导致业务超时 始终在从节点或低峰期执行
MONITOR长时间运行 撑爆客户端输出缓冲区,连接断开 限制采集时间 ≤ 60秒,使用管道重定向
仅依赖SLOWLOG判断热点 漏掉高QPS但低延迟的Key 必须结合客户端统计或MONITOR
客户端统计未做本地聚合 每个请求都上报,增加网络开销 使用滑动窗口本地聚合后批量上报

通过上述四种手段的组合,可以构建一套覆盖“实时-准实时-离线”全场景的热点Key识别体系,为后续的削峰与缓存策略提供精准的数据支撑。