外观
监控与慢日志:只看这几个数
Redis 的监控不需要几十个面板。六个指标就能覆盖绝大多数事故,慢日志和延迟监控负责定位具体命令。
场景:快到出事时才看指标就晚了
需要常驻采集的三类东西:
- 可用性:进程在不在、主从链路通不通。
- 容量:内存水位、淘汰速率、连接数。
- 性能:每秒操作数、慢命令、延迟毛刺。
一、慢日志
配置
bash
redis-cli -a '密码' config set slowlog-log-slower-than 10000
redis-cli -a '密码' config set slowlog-max-len 256
redis-cli -a '密码' config rewrite| 参数 | 单位 | 含义 |
|---|---|---|
slowlog-log-slower-than | 微秒 | 超过这个时间就记录。10000 = 10ms |
slowlog-max-len | 条数 | 环形队列长度,超出丢最旧的 |
生产建议 10000(10ms)。设 0 会记录所有命令(等于 MONITOR,千万别),设 -1 关闭。
查看
bash
redis-cli -a '密码' slowlog get 5text
1) 1) (integer) 3812
2) (integer) 1761548211
3) (integer) 48311
4) 1) "HGETALL"
2) "cart:30012"
5) "10.0.0.55:51244"
6) "order-service"
2) 1) (integer) 3811
2) (integer) 1761548188
3) (integer) 12064
4) 1) "KEYS"
2) "session:*"
5) "10.0.0.61:39882"
6) ""字段顺序:
| 位置 | 含义 |
|---|---|
| 1 | 日志 ID,递增 |
| 2 | Unix 时间戳 |
| 3 | 执行耗时,微秒(48311 = 48ms) |
| 4 | 命令与参数(长参数会被截断) |
| 5 | 客户端地址 |
| 6 | 客户端名(CLIENT SETNAME 设置,能快速定位哪个服务) |
bash
redis-cli -a '密码' slowlog len # 当前积压多少条
redis-cli -a '密码' slowlog reset # 清空三个高频元凶
| 命令 | 为什么慢 |
|---|---|
KEYS pattern | 全库遍历,O(N),生产禁用 |
HGETALL / SMEMBERS / LRANGE 0 -1 | 大 key 一次性取全量 |
DEL bigkey | 同步释放内存 |
FLUSHALL / FLUSHDB | 同 DEL,一堆 key |
SORT | O(N log N) 且可能占大量内存 |
| Lua 脚本里的循环 | 整段串行执行,期间所有请求排队 |
客户端名一定要设
CLIENT SETNAME order-service 之后,慢日志第 6 个字段就是它。出事时能直接定位到服务,而不是拿一个 IP 一个个查。
二、延迟监控(Latency Monitor)
慢日志只记命令执行时间,不记等 CPU / 等网络 / 被 fork 阻塞的时间。延迟监控补上这块。
bash
redis-cli -a '密码' config set latency-monitor-threshold 100
redis-cli -a '密码' config rewrite阈值单位是毫秒,100 表示记录超过 100ms 的事件。
bash
redis-cli -a '密码' latency latest
redis-cli -a '密码' latency history fork
redis-cli -a '密码' latency resettext
1) 1) "fork"
2) (integer) 1761548102
3) (integer) 312
4) (integer) 890
2) 1) "command"
2) (integer) 1761548211
3) (integer) 148
4) (integer) 231字段:事件名、最后发生时间戳、最后一次耗时(ms)、历史最大耗时(ms)。
常见事件名:
| 事件 | 含义 |
|---|---|
fork | fork 子进程耗时(BGSAVE/BGREWRITEAOF) |
command | 普通命令耗时 |
expire-cycle | 过期删除循环耗时 |
eviction-cycle | 淘汰循环耗时 |
aof-write / aof-fsync-always | AOF 写/同步耗时 |
fork 事件动辄几百毫秒,说明堆太大或页表太碎——这是"每隔几十分钟出现一次 300ms 毛刺"的典型根因。
bash
curl -s localhost:9121/metrics 2>/dev/null | head -3 # 装了 redis_exporter 才有三、INFO 的关键字段
bash
redis-cli -a '密码' info按段挑要看的:
server
text
redis_version:7.2.5
redis_mode:standalone
uptime_in_seconds:864000
hz:10
config_file:/etc/redis/6379.confredis_mode 有 standalone / sentinel / cluster 三种,排查前先确认自己连的是哪种。
clients
text
connected_clients:184
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:20480
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0connected_clients接近maxclients:要么连接泄漏,要么池配太大。blocked_clients长期 > 0:有BLPOP/BRPOP在等,正常(队列场景),但配合timeout设置不当会堆积。
stats
text
total_connections_received:1823411
total_commands_processed:98421344
instantaneous_ops_per_sec:12480
total_net_input_bytes:1843201233
total_net_output_bytes:9832112311
rejected_connections:0
expired_keys:1842934
evicted_keys:0
keyspace_hits:98123445
keyspace_misses:1209384
pubsub_channels:12
pubsub_patterns:0
latest_fork_usec:3120
total_forks:184必看换算:
text
命中率 = keyspace_hits / (keyspace_hits + keyspace_misses)
= 98123445 / 99332829 ≈ 98.78%| 指标 | 健康值 | 异常含义 |
|---|---|---|
| 命中率 | > 90% | 低 = key 太分散、TTL 太短、缓存穿透 |
evicted_keys | 缓存场景允许增长 | 增长过快 = 内存不够 |
rejected_connections | 0 | >0 = 连接数打满,已开始拒绝 |
latest_fork_usec | < 100000(100ms) | 大 = fork 阻塞主线程 |
expired_keys | 正常增长 | 突增 = 有大量集中过期 |
instantaneous_ops_per_sec 要和你自己的 QPS 曲线对齐看。它突然翻倍,可能是缓存击穿导致全部打回源。
memory
见 内存治理,重点 used_memory / maxmemory / mem_fragmentation_ratio。
persistence
见 持久化,重点 rdb_last_bgsave_status / aof_last_write_status。
replication
见 主从复制,重点 master_link_status / master_last_io_seconds_ago。
keyspace
text
db0:keys=182344,expires=120334,avg_ttl=3612841expires 长期远小于 keys,说明大量 key 没设 TTL,最终会把内存吃满。
cpu
text
used_cpu_sys:4812.31
used_cpu_user:9123.44
used_cpu_sys_children:120.11
used_cpu_user_children:481.22used_cpu_sys 高说明系统调用多(大量网络 IO / fsync),used_cpu_user 高说明命令计算重(复杂 Lua、大 key 遍历)。
四、客户端连接排查
bash
redis-cli -a '密码' client list | head -10text
id=182341 addr=10.0.0.55:51244 laddr=10.0.0.11:6379 fd=18 name=order-service age=1204 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=26 qbuf-free=20448 argv-mem=10 multi-mem=0 tot-net-in=1042 tot-net-out=18234 rbs=1024 rbp=0 obl=0 oll=0 omem=0 tot-mem=20512 events=r cmd=client|list user=default redir=-1 resp=2关键字段:
| 字段 | 含义 |
|---|---|
name | 客户端名,强烈建议业务都设 |
age | 连接存活秒数 |
idle | 空闲秒数 |
cmd | 最后执行的命令 |
omem | 输出缓冲区占用字节数 |
tot-net-in/out | 累计收发字节 |
qbuf | 输入缓冲区,大 = pipeline 太大 |
按名字统计连接数
bash
redis-cli -a '密码' client list | awk '{for(i=1;i<=NF;i++) if($i ~ /^name=/) print $i}' | sort | uniq -c | sort -rntext
120 name=order-service
48 name=
16 name=report-job- 空
name=的多,说明有客户端没设名字,先补上。 - 单个服务连接数远超池配置,就是连接泄漏(借了没还)。
杀掉指定连接
bash
redis-cli -a '密码' client kill id 182341
redis-cli -a '密码' client kill type normal skipme yesclient kill type normal 会杀掉自己
redis-cli 本身也是 normal 类型连接。加 skipme yes 才不会被自己杀掉;但这一刀下去业务所有长连接都会断,务必确认是在处理"连接泄漏后重启业务前"这种场景。
其它客户端管理
bash
redis-cli -a '密码' config get maxclients
redis-cli -a '密码' config get timeout # 空闲连接超时(秒),0=不超时
redis-cli -a '密码' client no-evict on # 保护关键连接不被淘汰(7.0+)
redis-cli -a '密码' client info # 看自己这条连接的详情五、命令行快速体检
bash
# 每秒刷新关键指标
redis-cli -a '密码' --stat
# 单次往返延迟(客户端到服务端)
redis-cli -a '密码' --latency
# 排除网络,测服务端自身调度延迟(要在服务端本机跑)
redis-cli --intrinsic-latency 5
# 逐节点扫 key,不阻塞
redis-cli -a '密码' --scan --pattern 'session:*' | head
# 压测(别在生产做)
redis-cli -a '密码' --latency-history -i 5--stat 输出:
text
------- data ------ --------------------- load -------------------- - child -
keys mem clients blocked requests connections
182344 2.04G 184 0 984213 (+12480) 1823411--intrinsic-latency 5 输出:
text
Latency: 0.9 us average, 4.2 us max.如果 intrinsic-latency 的 max 到了几百微秒甚至毫秒,说明是宿主机问题(CPU 抢占、NUMA、虚拟化抖动),不是 Redis 配置问题。
六、告警阈值参考
| 指标 | 警告 | 严重 |
|---|---|---|
| 内存使用率 | > 70% maxmemory | > 85% |
| 连接数 | > 70% maxclients | > 85% |
| 命中率 | < 90% | < 70% |
master_link_status | down 持续 10s | down 持续 60s |
rdb_last_bgsave_status | err | 连续 3 次 err |
latest_fork_usec | > 100ms | > 500ms |
evicted_keys 增速 | > 100/s | > 1000/s |
blocked_clients | 持续 > 100 | 持续增长 |
| 主从 offset 差 | > 10MB | > 100MB |
采集用 redis_exporter + Prometheus 是标准组合,但先保证有人看。没有告警通道的面板,出事后没人会打开。
七、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
| 上了监控但没人告警 | 只有面板没有通道 | 阈值 + 钉钉/电话 |
MONITOR 一开就雪崩 | 每条命令都广播 | 生产禁用,用 slowlog 代替 |
| 慢日志一直是空的 | slowlog-log-slower-than 设成了 1000000(1 秒) | 调到 10000 |
慢日志全是 HGETALL | 大 key | 拆 key 或改 HSCAN |
| 延迟毛刺找不到原因 | 没开 latency-monitor | 开阈值 100ms,看 fork 事件 |
| 命中率突然大跌 | 缓存击穿 / key 前缀改了 | 对照业务发布记录 |
connected_clients 缓慢上涨 | 连接池泄漏 | client list 按 name 分组,查代码 |
| 指标都正常但业务超时 | 网络 / 客户端 GC / 池等待 | 看客户端侧指标,别只盯 Redis |