Skip to content

监控与慢日志:只看这几个数 ​

Redis 的监控不需要几十个面板。六个指标就能覆盖绝大多数事故,慢日志和延迟监控负责定位具体命令。

场景:快到出事时才看指标就晚了 ​

需要常驻采集的三类东西:

  1. 可用性:进程在不在、主从链路通不通。
  2. 容量:内存水位、淘汰速率、连接数。
  3. 性能:每秒操作数、慢命令、延迟毛刺。

一、慢日志 ​

配置 ​

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 5
text
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,递增
2Unix 时间戳
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
SORTO(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 reset
text
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)。

常见事件名:

事件含义
forkfork 子进程耗时(BGSAVE/BGREWRITEAOF)
command普通命令耗时
expire-cycle过期删除循环耗时
eviction-cycle淘汰循环耗时
aof-write / aof-fsync-alwaysAOF 写/同步耗时

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.conf

redis_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:0
  • connected_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_connections0>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=3612841

expires 长期远小于 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.22

used_cpu_sys 高说明系统调用多(大量网络 IO / fsync),used_cpu_user 高说明命令计算重(复杂 Lua、大 key 遍历)。

四、客户端连接排查 ​

bash
redis-cli -a '密码' client list | head -10
text
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 -rn
text
    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 yes

client 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_statusdown 持续 10sdown 持续 60s
rdb_last_bgsave_statuserr连续 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