Redis 缓存监控体系深度解析:从 BigKeys 到慢查询
Redis 作为高性能缓存,在生产环境中必须建立完善的监控体系。本文将深入剖析 BigKeys、HotKeys、慢查询 三大核心监控维度,并提供生产级诊断与优化方案。
一、BigKeys(大Key)监控与治理
1.1 什么是大Key?
大Key定义:单个 Key 的内存占用过大,通常指:
- String 类型:value > 10KB(或 > 1MB)
- Hash/List/Set/Zset:元素数量 > 5000 个(或总大小 > 10MB)
大Key危害:
- 阻塞单线程 :Redis 单线程模型,操作大Key会阻塞其他请求,导致延迟飙升(从微秒级到秒级)
- 内存溢出:集群架构下,大Key导致某个子节点内存率先耗尽,引发 OOM
- 网络拥塞:大Key的传输占用大量带宽,影响其他请求
- 删除卡顿:DEL 大Key会阻塞数秒甚至数十秒
1.2 大Key识别方法
**方法1:redis-cli --bigkeys(官方推荐)
bash
# 遍历所有Key,分析每种类型的最大Key
redis-cli -h <host> -p <port> -a <password> --bigkeys
# 扫描间隔 0.1 秒(避免影响业务)
redis-cli --bigkeys -i 0.1
# 输出示例:
# Sampled 1000000 keys in the hash slot 0...
# Sampled 1000000 keys in the hash slot 1...
# Biggest string found 'user:profile:1000' has 10485760 bytes
# Biggest hash found 'order:items:2024' has 125000 fields
优点:无需安装插件,官方原生支持
缺点 :对性能有影响,禁止在业务高峰期使用
方法2:离线 RDB 文件分析(零影响)
bash
# 下载 RDB 文件到本地分析
redis-cli --rdb dump.rdb
# 使用 rdb-tools 分析
rdb --command memory dump.rdb > memory.csv
# 分析结果排序
sort -t, -k4nr memory.csv | head -20
阿里云/华为云控制台 :提供离线全量 Key 分析功能,对线上服务无影响
方法3:MEMORY USAGE 精确查询
bash
# 查询单个 Key 的内存占用(精确)
MEMORY USAGE "user:profile:1000"
# 返回:10485760 (bytes)
# 配合 SCAN 批量扫描
redis-cli --scan --pattern "user:*" | xargs -L 1 redis-cli MEMORY USAGE
1.3 大Key解决方案
方案1:数据拆分(核心策略)
大 Hash 拆分:
java
// 原大Key:user:profile:{userId} 包含100万字段
// 拆分后:user:profile:{userId}:{hash(userId)%100}
int shard = userId % 100;
String key = "user:profile:" + userId + ":" + shard;
// 读取时聚合
List<String> results = jedisCluster.hmget(
"user:profile:" + userId + ":*",
"field1", "field2"
);
大 String 拆分:
java
// 将 10MB JSON 拆分为多个 Key
String baseKey = "article:content:" + articleId + ":";
jedisCluster.set(baseKey + "part1", json.substring(0, 1024*1024));
jedisCluster.set(baseKey + "part2", json.substring(1024*1024, 2048*1024));
// 读取时拼接
方案2:数据压缩
java
// 使用 LZ4/Snappy 压缩
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor()
.compress(originalJson.getBytes());
// 存储为二进制
jedisCluster.set(key.getBytes(), compressed);
方案3:异步删除(UNLINK)
bash
# DEL 会阻塞,UNLINK 会后台删除
UNLINK "user:profile:1000"
1.4 大Key监控与告警
定时任务扫描:
java
@Scheduled(cron = "0 0 3 * * ?") // 每日凌晨低峰期
public void scanBigKeys() {
Set<String> keys = jedisCluster.keys("user:*");
for (String key : keys) {
Long size = jedisCluster.memoryUsage(key);
if (size > 10 * 1024 * 1024) { // > 10MB
alarmService.send("大Key告警: " + key + " 大小: " + size + "bytes");
}
}
}
阿里云/华为云:控制台配置大Key自动告警阈值
二、HotKeys(热Key)监控与治理
2.1 什么是热Key?
热Key定义:访问频率极高的 Key,通常 QPS > 5000
热Key危害:
- CPU 打满:单个 Key 的请求由单核处理,成为性能瓶颈
- 单点瓶颈:集群架构下,某个分片节点压力过大
- 缓存击穿:热Key过期瞬间,请求洪峰打爆数据库
典型案例:
- 秒杀活动商品详情页
- 热门视频弹幕
- 首页 Banner 配置
2.2 热Key识别方法
方法1:redis-cli --hotkeys(推荐)
bash
# Redis 4.0+ 原生支持
redis-cli -h <host> -p <port> -a <password> --hotkeys
# 输出示例:
# Summary:
# Key 1: "product:detail:9527" QPS: 15234
# Key 2: "user:session:10086" QPS: 8921
# **注意**:对性能有影响,**禁止高峰期使用**
方法2:MONITOR 命令(慎用)
bash
# 实时监控所有命令(性能杀手,降低50%性能)
redis-cli MONITOR | grep "GET\|SET"
# 统计 key 访问频率
redis-cli MONITOR | awk '{print $2}' | sort | uniq -c | sort -nr | head -20
# **严重警告**:只能在非高峰期短时间使用
方法3:业务层埋点(最准确)
java
// 在访问 Redis 处埋点
public String get(String key) {
long start = System.nanoTime();
String value = jedisCluster.get(key);
long qps = metrics.recordQuery(key, start); // 记录 QPS
if (qps > 5000) {
hotkeyService.report(key, qps); // 上报热Key
}
return value;
}
阿里云/华为云 :控制台提供实时热Key分析,对业务无影响
2.3 热Key解决方案
方案1:本地缓存(L1)最常用
java
// Caffeine 本地缓存(有效期 1-2 分钟)
private final Cache<String, String> localCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(Duration.ofMinutes(2))
.build();
public String getProductDetail(Long productId) {
String key = "product:detail:" + productId;
// 1. 本地缓存
String json = localCache.getIfPresent(key);
if (json != null) return json;
// 2. Redis 集群
json = jedisCluster.get(key);
if (json != null) {
localCache.put(key, json); // 回填本地缓存
return json;
}
// 3. 数据库
Product product = productMapper.selectById(productId);
json = JSON.toJSONString(product);
localCache.put(key, json);
jedisCluster.setex(key, 300, json);
return json;
}
方案2:读写分离(主从架构)
yaml
# redis.conf
# 从节点配置为只读
slave-read-only yes
java
// 读从节点
Jedis slaveJedis = new Jedis("slave-ip", 6379);
String value = slaveJedis.get("hotkey");
// 写主节点
jedisCluster.set("hotkey", newValue); // 自动同步到从
方案3:热Key复制 + 随机访问
java
// 将 hotkey 复制为多个副本
int replicaCount = 10;
for (int i = 0; i < replicaCount; i++) {
String replicaKey = "hotkey:" + i;
jedisCluster.set(replicaKey, value);
}
// 读取时随机路由
int randomIndex = ThreadLocalRandom.current().nextInt(replicaCount);
String replicaKey = "hotkey:" + randomIndex;
String value = jedisCluster.get(replicaKey);
2.4 热Key监控与告警
实时告警:
java
// 基于埋点的实时告警
@Scheduled(fixedRate = 1000) // 每秒检查
public void checkHotkeys() {
Map<String, Long> stats = metrics.getQpsStats();
stats.forEach((key, qps) -> {
if (qps > 5000) {
alarmService.send("热Key告警: " + key + " QPS: " + qps);
// 自动触发本地缓存
enableLocalCacheForKey(key);
}
});
}
三、慢查询分析与优化
3.1 慢查询日志
配置:
bash
# redis.conf
slowlog-log-slower-than 10000 # 超过 10ms 记录(微秒)
slowlog-max-len 1000 # 保留最近 1000 条
查看慢查询:
bash
# 查看最近 10 条慢查询
redis-cli SLOWLOG GET 10
# 输出格式:
# 1) (integer) 123 # 唯一ID
# 2) (integer) 1676888923 # 时间戳
# 3) (integer) 15000 # 执行时长(微秒)= 15ms
# 4) 1) "HGETALL" # 命令
# 2) "user:profile:1000" # Key
# 5) "192.168.1.10:54321" # 客户端地址
清空慢查询日志:
bash
SLOWLOG RESET
3.2 慢查询根因分析
根因1:高复杂度命令 O(N)
典型慢命令:
| 命令 | 时间复杂度 | 场景 |
|---|---|---|
KEYS pattern |
O(N) | 遍历所有 Key |
HGETALL |
O(N) | 读取大 Hash |
SMEMBERS |
O(N) | 读取大 Set |
SORT |
O(N+M*log(M)) | 排序 |
SINTER |
O(N*M) | 集合交集 |
优化方案:
bash
# KEYS * → SCAN 0 渐进式遍历
SCAN 0 MATCH "user:*" COUNT 1000
# HGETALL → HSCAN 分批读取
HSCAN "user:profile:1000" 0 COUNT 100
# SMEMBERS → SSCAN
SSCAN "hot:set" 0 COUNT 100
根因2:大Key操作
bash
# 删除 10MB 的 Key(阻塞 50ms)
DEL "bigkey:content"
# 优化:异步删除
UNLINK "bigkey:content" # 非阻塞,后台线程删除
根因3:热Key集中访问
bash
# 单个 Key 的 QPS > 10000,CPU 单核打满
# 解决方案见 "热Key治理" 章节
3.3 慢查询监控与告警
定时分析:
java
@Scheduled(cron = "0 */5 * * * ?") // 每 5 分钟
public void analyzeSlowLog() {
List<SlowLog> logs = jedisCluster.slowlogGet(100);
logs.stream()
.filter(log -> log.getExecutionTime() > 50000) // > 50ms
.forEach(log -> {
alarmService.send("慢查询告警: " + log.getCommand() + " " +
log.getKey() + " 耗时: " + log.getExecutionTime() + "μs");
});
}
慢查询可视化:
- 阿里云/华为云:控制台自动展示慢查询 Top10
- 自建监控 :通过
SLOWLOG GET采集到 Prometheus + Grafana
四、综合监控体系:从指标到告警
4.1 监控指标体系
| 指标类别 | 核心指标 | 阈值 | 监控工具 |
|---|---|---|---|
| 性能 | QPS、延迟 | P99 < 10ms | INFO stats |
| 内存 | 内存占用、碎片率 | used_memory_human < 80% | INFO memory |
| 大Key | Key 大小 | > 10MB 告警 | --bigkeys |
| 热Key | Key 访问频率 | QPS > 5000 告警 | --hotkeys |
| 慢查询 | 执行时长 | > 10ms 告警 | SLOWLOG GET |
| 命中率 | keyspace_hits / (hits + misses) | > 90% | INFO keyspace |
4.2 生产级告警配置
Prometheus + Grafana 监控大盘:
yaml
# Prometheus 采集配置
- job_name: 'redis'
static_configs:
- targets: ['redis:9121']
scrape_interval: 15s
# 告警规则
- alert: RedisHighMemoryUsage
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "Redis 内存使用率超过 80%"
Redis Exporter 指标:
bash
# 安装 redis_exporter
docker run -d --name redis_exporter \
-p 9121:9121 \
oliver006/redis_exporter \
--redis.addr=redis://192.168.1.20:6379
4.3 自动化治理闭环
监控采集
告警触发
根因分析
大Key?
热Key?
慢查询?
自动拆分/压缩
启用本地缓存
SQL优化/SCAN替代
效果验证
监控收敛
京东故障排查模板:
- 快速诊断 :
slowlog、--hotkeys、--bigkeys - 根因定位:O(N)命令、大Key、热Key
- 紧急止血:UNLINK、本地缓存、读写分离
- 长期优化:代码改造、监控闭环
五、云厂商工具对比
| 工具 | 大Key分析 | 热Key分析 | 慢查询 | 优点 | 价格 |
|---|---|---|---|---|---|
| 阿里云 Redis | ✅ 离线分析 | ✅ 实时监控 | ✅ 自动告警 | 对业务无影响 | 免费 |
| 华为云 DCS | ✅ 离线分析 | ✅ 实时监控 | ✅ 自动告警 | 集成监控平台 | 免费 |
| redis-cli | ✅ --bigkeys | ✅ --hotkeys | ✅ SLOWLOG | 原生支持 | 开源免费 |
| redis_exporter | ❌ | ❌ | ✅ 采集 | Prometheus集成 | 开源免费 |
六、生产环境最佳实践
6.1 监控 checklist
- 每日扫描 :凌晨低峰期运行
--bigkeys - 热Key监控:接入云厂商工具或业务埋点
- 慢Query告警:配置 > 10ms 的告警规则
- 内存水位:设定 80% 告警阈值
- 命中率:目标 > 90%,低于 80% 立即排查
6.2 优化口诀
大Key三方案:拆分、压缩、UNLINK
热Key三方案:本地缓存、读写分离、分片
慢查询三方案:SCAN、HSCAN、SSCAN
监控三要素:QPS、内存、命中率
总结
| 监控项 | 识别工具 | 危害 | 解决方案 | 优先级 |
|---|---|---|---|---|
| BigKeys | --bigkeys、RDB分析 |
阻塞单线程、OOM | 拆分、压缩、UNLINK | 🔴 高 |
| HotKeys | --hotkeys、业务埋点 |
CPU打满、单点瓶颈 | 本地缓存、读写分离 | 🔴 高 |
| 慢查询 | SLOWLOG GET |
阻塞其他请求 | SCAN替代KEYS、分批读取 | 🟡 中 |
Redis 监控的本质是 "防范于未然" 。通过自动化工具识别风险,通过分级告警快速响应,通过闭环治理持续优化,才能保障缓存系统的高可用与高性能。