Redis 线上排障与延迟诊断:SLOWLOG、LATENCY 与阻塞命令全流程

Redis 线上延迟排障完整指南:延迟问题的三层分类(网络/客户端/服务端)、SLOWLOG 配置与慢命令定位、LATENCY MONITOR 事件记录与 LATENCY DOCTOR 自动诊断、INFO 关键指标解读(延迟百分位、rejected_connections、blocked_clients、碎片率)、CLIENT LIST 与 CLIENT PAUSE 客户端管理、大 Key 与 O(N) 命令识别、fork 与 AOF 重写抖动、THP 与 swap 排查、完整排障流程与真实案例复盘

线上 Redis 变慢是运维最常接到的一类告警,也是最难定位的一类问题:它可能来自一条 O(N) 命令、一次 fork 抖动、一次 AOF 重写、一个打满网卡的大 Key,甚至一段代码里的 KEYS *。表象都是「延迟升高」,根因却分散在应用、Redis、操作系统、网络四个层面。

有效的排障不是凭经验猜,而是有一套从指标到根因的收敛路径:先用 INFO 判断延迟出在哪一层,用 SLOWLOG 找出慢命令,用 LATENCY MONITOR 捕获事件,再用 CLIENT LIST 定位具体客户端。本文给出这套完整方法论,从工具用法到真实案例。


一、延迟问题的分类与排查方法论

1.1 延迟的三层来源

客户端到 Redis 之间的网络层(带宽打满、丢包、跨 AZ、连接数过多)会让所有命令均匀变慢;客户端层的连接池不足、大 value 传输、阻塞式调用只影响部分客户端;服务端层的慢命令、大 Key、fork、AOF 重写、内存交换则表现为周期性或突发性尖刺。

1.2 排查的收敛路径

先确认现象(是所有命令还是特定命令、周期性还是持续);再分层定位(redis-cli --latency 测本机延迟,从客户端测网络延迟);然后找慢命令(SLOWLOG GET 100)与事件(LATENCY MONITOR 加 LATENCY DOCTOR);接着看 INFO all 的关键字段与 CLIENT LIST 的异常连接;最后看系统的 CPU、内存、磁盘、网络、THP 与 swap。

1.3 第一手工具:redis-cli latency

redis-cli --latency                    # min: 0, max: 3, avg: 0.12
redis-cli --latency-histogram --nb 1000 --history 100   # 6.2+ 直方图
redis-cli --latency -i 1               # 持续监控

--latency 在与 Redis 同机执行时测的是服务端处理延迟;在客户端机器执行时测的是网络加服务端总延迟。两者对比即可分离出网络贡献。

1.4 延迟的两种形态

持续偏高的特征是平均延迟整体上移,常见根因是 CPU 饱和、网络带宽与慢命令常态化;周期性尖刺每隔固定时间出现峰值,多与 fork、AOF 重写、定时任务或 cron 扫描有关;突发尖刺无规律偶发,往往是大 Key 操作、内存交换或 GC。

周期性尖刺最容易被误判:平均值看起来正常,但 p99 每隔几分钟就飙升一次。用 redis-cli --latency 长跑观察,或看监控的 p99 曲线,能立刻发现规律性。


二、SLOWLOG:慢命令的第一现场

2.1 配置与查看

# redis.conf:超过 10000 微秒(10ms)的命令记为慢查询;-1 关闭,0 记录全部
slowlog-log-slower-than 10000
slowlog-max-len 128
redis-cli CONFIG SET slowlog-log-slower-than 5000   # 运行时调整
redis-cli CONFIG SET slowlog-max-len 1024
redis-cli CONFIG REWRITE

redis-cli SLOWLOG GET 10
# 1) 1) (integer) 14              -- 日志 ID
#    2) (integer) 1696123456      -- 发生时间戳
#    3) (integer) 15234           -- 耗时(微秒)
#    4) 1) "KEYS" 2) "user:*"     -- 命令与参数
#    5) "10.0.0.5:52341"          -- 客户端地址
#    6) "app-server-1"            -- 客户端名称

redis-cli SLOWLOG LEN           # 当前记录条数
redis-cli SLOWLOG RESET         # 清空

生产环境建议设为 10000(10ms)。若目标是发现一切可疑命令,可临时降到 1000(1ms),但会产生大量日志,观察完立即调回。

2.2 从慢日志识别问题模式

KEYS pattern 是全库扫描 O(N),应改 SCAN 游标遍历;HGETALL 大 Hash 会返回巨量数据,应改 HSCAN 或分片;LRANGE 0 -1 大 List 全量读取,应改分页 LRANGE 0 99;SMEMBERS 大 Set 应改 SSCAN;SORT 大集合是 O(N log N),应改用 ZSet 预排序;DEL 大 Key 会阻塞释放,应改 UNLINK;FLUSHALL 应禁用或走 ASYNC;长 EVAL 脚本应拆分逻辑。

# 统计慢日志中的命令分布
redis-cli SLOWLOG GET 128 | grep -A1 '^\s*4)' | grep -oE '"[A-Z]+"' | sort | uniq -c | sort -rn

2.3 慢日志的盲区

SLOWLOG 只记录命令执行时间,不含网络传输时间,因此一个传输 50MB 大 Key 的 GET 可能不慢(执行快)但客户端侧延迟极高。它也不含排队时间(命令在客户端连接缓冲区排队不计入)、不含 fork 阻塞(fork 期间命令无法执行但日志不记录)、只记录超过阈值的、环形缓冲会覆盖旧记录。

因此它是必要但不充分的诊断工具:它告诉你「哪些命令慢」,但 fork、网络、内存交换这些非命令因素需要靠 LATENCY MONITOR 与系统指标。


三、LATENCY MONITOR 与 LATENCY DOCTOR

3.1 事件监控

Redis 内部会记录可能导致阻塞的事件,这是 SLOWLOG 无法覆盖的部分。

redis-cli LATENCY HISTORY fork
# 1) 1) (integer) 1696123456      -- 时间戳
#    2) (integer) 42              -- 该事件的延迟(毫秒)

redis-cli LATENCY RESET fork
redis-cli LATENCY LATEST
# 1) 1) "fork" 2) 1696123456 3) 42 4) 128
#    事件名      最近时间       最近延迟   历史最大延迟

3.2 事件类型一览

fork 执行 fork 的耗时(内存大、THP 开启);aof-fsync-always 每次 fsync 耗时(磁盘慢);aof-write AOF 写入耗时(磁盘 IO 瓶颈);aof-write-pending-fsync 等待 fsync 的时间(磁盘拥塞);aof-write-active-child 等待子进程写 AOF;aof-rewrite-diff-write 重写期间写增量;aof-rename 重写完成后改名(文件系统慢);expire-cycle 过期键清理周期(大量键同时过期);eviction-cycle 淘汰周期(内存打满频繁淘汰);eviction-del 淘汰删除耗时(大 Key 淘汰);active-defrag-cycle 碎片整理周期(CPU 竞争)。

3.3 LATENCY DOCTOR 与命令级追踪

redis-cli LATENCY DOCTOR
# Dave, I have observed latency spikes in this Redis instance.
# fork: 42ms latency spike happened 3 times in the last 5 minutes.
#   This is usually caused by a large memory allocation or THP.

redis-cli CONFIG SET latency-tracking yes
redis-cli CONFIG SET latency-tracking-info-percentiles "50 99 99.9"
redis-cli LATENCY HISTOGRAM
# 1) "get" 2) 1) "calls" 2) (integer) 1023456 3) "histogram_usec" ...

LATENCY DOCTOR 会读取所有记录的事件,给出人类可读的诊断建议,是排障的第一步——很多问题(如 THP、fork 抖动)看一眼输出就有方向。LATENCY HISTOGRAM(7.0+)比 SLOWLOG 更全面:它给出每个命令的完整延迟分布,而不只是超过阈值的个例,可用来发现「平均很快但 p99 很差」的命令。

3.4 开启事件监控

redis-cli CONFIG SET latency-monitor-threshold 100
redis-cli CONFIG REWRITE

阈值 latency-monitor-threshold 默认 0(关闭)。生产环境务必设为 100(即记录超过 100ms 的事件)。阈值过高会漏掉问题,过低会产生噪声。


四、INFO 关键指标解读

4.1 延迟相关字段与关键指标

redis-cli INFO latencystats
# latency_percentiles_usec_get:p50=0.102,p99=0.251,p99.9=1.023
redis-cli INFO commandstats | grep usec_per_call | sort -t= -k4 -rn | head -10
# cmdstat_hgetall:calls=1234,usec=567890,usec_per_call=460.2

instantaneous_ops_per_sec(stats,当前 QPS,接近容量上限告警);rejected_connections(stats,因 maxclients 被拒的连接,持续增长告警);expired_keys(stats,累计过期键数,突增说明集中过期);evicted_keys(stats,累计淘汰键数,突增说明内存不足);blocked_clients(clients,阻塞中的客户端数,持续大于 0 告警);mem_fragmentation_ratio(memory,碎片率,大于 1.5 或小于 1 告警);latest_fork_usec(stats,最近一次 fork 耗时,大于 100000 告警);aof_last_write_status(persistence,上次 AOF 写状态,非 ok 告警);master_link_status(replication,主从链路,非 up 告警)。

4.2 碎片率与内存

redis-cli INFO memory | grep -E 'used_memory_human|used_memory_rss_human|mem_fragmentation_ratio|maxmemory_human'
# used_memory_human:3.20G / used_memory_rss_human:5.80G / mem_fragmentation_ratio:1.81

碎片率在 1.0~1.5 属正常;大于 1.5 说明内存碎片多、RSS 远大于数据,应开启 activedefrag;小于 1.0 说明使用了 swap,属于严重问题,必须关闭 swap 或扩容。mem_fragmentation_ratio < 1 是最危险的信号:说明操作系统已经把部分内存换出到磁盘,后续任何访问该页的命令都会触发缺页中断,延迟瞬间飙升到毫秒甚至秒级。

4.3 网络与连接

redis-cli INFO clients 会给出 connected_clients:1523、maxclients:10000、blocked_clients:3、client_recent_max_output_buffer:0 等字段。client_recent_max_output_buffer 很大说明有客户端读取慢、输出缓冲堆积;blocked_clients 持续大于 0 说明有阻塞命令或脚本;connected_clients 接近 maxclients 说明连接泄漏或连接池配置过大。


五、客户端排查:CLIENT LIST 与 PAUSE

5.1 CLIENT LIST 关键字段

redis-cli CLIENT LIST
# id=5 addr=10.0.0.5:52341 fd=8 name=app-1 age=3600 idle=0 flags=N db=0
#   qbuf=0 qbuf-free=20448 obl=0 oll=0 omem=0 tot-mem=1744 events=r cmd=get
redis-cli CLIENT INFO 5          # 查看单个连接详情

idle 空闲秒数(大量长空闲连接说明连接池过大);qbuf 查询缓冲区已用字节(很大说明客户端在批量发送);obl 输出缓冲区长度(持续增长说明客户端消费慢);omem 输出缓冲占用内存(大量占用可能触发 OOM);cmd 最后执行的命令(定位卡在什么命令上);age 连接存活秒数(异常长可能是泄漏)。

5.2 输出缓冲区限制与 CLIENT KILL

client-output-buffer-limit 的三种客户端类别分别对应普通客户端、副本与订阅客户端,形如 normal 0 0 0、replica 256mb 64mb 60、pubsub 32mb 8mb 60。其中 normal 0 0 0 表示不限制普通客户端的输出缓冲,这是常见隐患:一个消费慢的客户端(如 MONITOR 或大量 KEYS 返回)可以让 Redis 内存暴涨,生产建议改为 normal 256mb 64mb 60。

5.3 CLIENT KILL 与 CLIENT PAUSE

redis-cli CLIENT KILL ID 1523
redis-cli CLIENT KILL TYPE normal SKIPME yes    # 保留自己

redis-cli CLIENT PAUSE 10000            # 暂停 10 秒,默认 WRITE 模式
redis-cli CLIENT PAUSE 10000 ALL        # 读写全部暂停

CLIENT PAUSE 是故障转移的标准手段:在 Sentinel/Cluster 切换期间暂停客户端写入,避免切到新主后数据回退。ALL 模式会暂停所有命令,慎用。

5.4 连接命名与 MONITOR 的正确用法

redis-cli CLIENT NO-EVICT ON          # 标记连接不受内存淘汰影响(7.0+)
redis-cli CLIENT SETNAME app-server-1 # 给连接设置名称,便于排查
redis-cli CLIENT SETINFO LIB-NAME my-app LIB-VER 1.2.3   # 7.2+

给每个连接设名字是排障的基础设施:CLIENT LIST 里看到 name=app-order-service 比看到 addr=10.0.0.5:52341 有用得多,建议所有客户端在初始化时调用 CLIENT SETNAME。MONITOR 则会把每条命令复制给监控客户端,在 10 万 QPS 下就是 10 万条/秒的额外网络流量,本身就会造成延迟飙升,生产环境严禁长时间开启;如需统计命令分布,只能短时执行 timeout 5 redis-cli MONITOR | awk '{print $3}' | sort | uniq -c | sort -rn | head -20。


六、大 Key 与阻塞命令识别

6.1 阻塞命令清单

KEYS * 全库扫描 O(N) 应改 SCAN;FLUSHALL/FLUSHDB 释放全部内存应加 ASYNC;DEL 大 Key 同步释放应改 UNLINK;HGETALL/SMEMBERS/LRANGE 0 -1 返回巨量数据应改 HSCAN/SSCAN 分页;SORT/SINTERSTORE/ZUNIONSTORE 集合运算应预计算或限流;BITOP 大位图运算应分批;SETRANGE 超大偏移会分配大内存应限制偏移;长 EVAL 脚本应拆分限时;MIGRATE 同步迁移应用集群工具;DEBUG SLEEP 应禁用。

6.2 大 Key 快速定位

redis-cli --bigkeys            # 快速摸底
redis-cli --memkeys            # 内存维度扫描

# 精确排查:SCAN 遍历 + MEMORY USAGE,筛出大于 10MB 的键
redis-cli --scan --count 1000 | while read k; do
  s=$(redis-cli MEMORY USAGE "$k" SAMPLES 5)
  [ -n "$s" ] && [ "$s" -gt 10485760 ] && echo "$s $k"
done | sort -rn | head -20

大 Key 的完整治理方法可参考本专题的 大 Key 与热 Key 治理 一文。排障视角的关键是:大 Key 既是延迟的原因,也是延迟排查的干扰项——--bigkeys 本身就会扫描全库,务必用 -i 控制节奏。

6.3 键空间扫描与集中过期

redis-cli KEYS 'user:*'                          # 错误:阻塞全库
redis-cli SCAN 0 MATCH 'user:*' COUNT 100        # 正确:游标,每次少量
# 1) "17408"          -- 下一个游标
# 2) 1) "user:1" 2) "user:2" ...

redis-cli INFO stats | grep expired_keys         # expired_keys:1258432

SCAN 的 COUNT 是提示而非保证,实际返回数量可能更多或更少。SCAN 保证遍历期间一直存在的元素一定会被返回,但不保证不重复,客户端需自行去重。另外,大量键在同一时刻过期(如批量写入时统一设了 EXPIRE 3600)会在过期时刻触发密集的惰性删除与定期删除,造成周期性尖刺,对策是给 TTL 加随机抖动:ttl = 3600 + random.randint(-360, 360) 再 setex,即 TTL 加 ±10% 抖动。这是缓存雪崩的微观版本:不是全部失效,而是局部同时失效,抖动 5%~10% 就能把尖刺摊平。


七、fork 与 AOF 抖动

7.1 fork 的代价

RDB 快照与 AOF 重写都依赖 fork() 创建子进程。fork 本身需要复制页表,耗时与内存大小成正比:1GB 内存约 515ms,4GB 约 2050ms,16GB 约 80~300ms,64GB 则可能超过 1 秒。

用 redis-cli INFO stats | grep latest_fork_usec 可看到最近一次 fork 耗时(如 latest_fork_usec:42891 即 42.9ms),配合 redis-cli LATENCY HISTORY fork 看历史。

7.2 THP(透明大页)的致命影响

Transparent Huge Pages 会把 4KB 页合并为 2MB 页,fork 时复制页表的开销会放大数十倍,fork 耗时可能从 30ms 变成 1 秒。

cat /sys/kernel/mm/transparent_hugepage/enabled
# always [madvise] never     -- 方括号内是当前值
echo never > /sys/kernel/mm/transparent_hugepage/enabled   # 关闭 THP
echo never > /sys/kernel/mm/transparent_hugepage/defrag    # 关闭碎片整理

托管服务通常已默认关闭 THP。自建环境必须关闭,这是 Redis 官方反复强调的第一条系统调优建议。

7.3 Copy-On-Write 与内存翻倍

fork 后父子进程共享内存页,任何写操作都会触发写时复制(COW),把该页复制一份。写入越密集,COW 产生的额外内存越多,极端情况下内存用量接近翻倍。对策是预留 maxmemory 的 50% 作为 COW 余量(即 maxmemory 不超过物理内存的 50%~60%)、降低 RDB/AOF 重写频率、减少 fork 期间的高频写入。

7.4 AOF 配置与磁盘抖动

关键配置是 appendonly yes、appendfsync everysec、no-appendfsync-on-rewrite no、auto-aof-rewrite-percentage 100、auto-aof-rewrite-min-size 64mb。配合 redis-cli LATENCY LATEST 查看 aof-fsync-always、aof-write 等事件,用 iostat -x 1 5 关注磁盘 %util 是否接近 100%、await 是否远高于 svctm。

appendfsync always 每条命令都 fsync,数据最安全但延迟受磁盘 IOPS 限制;everysec 每秒 fsync,最多丢 1 秒数据、延迟低,是推荐值;no 交给操作系统,延迟最低但数据不可控。no-appendfsync-on-rewrite yes 会在重写期间暂停 fsync,降低延迟尖刺,但代价是重写期间可能丢失最多 30 秒数据。

从事件看根因:aof-fsync-always 尖刺说明磁盘 IOPS 不足(换 SSD 或改 everysec);aof-write 尖刺说明磁盘带宽打满(分离 AOF 到独立盘);aof-rename 慢说明文件系统(如 NFS)慢(改用本地盘);aof-rewrite-diff-write 慢说明重写期间写入量大(低峰期触发重写)。

很多「Redis 延迟尖刺」的根因就是在一个纯缓存实例上开启了不必要的持久化。先问一句「这份数据丢了会怎样」,如果答案是「从数据库重建即可」,就用 save "" 与 appendonly no 彻底关掉持久化,消除 fork 与 fsync 抖动。


八、网络、内核与客户端侧排查

8.1 网络层排查

ping -c 100 redis-host          # 网络往返延迟
sar -n DEV 1 5                  # 网卡带宽与丢包
netstat -s | grep -E 'retransmit|drop|overflow'
redis-cli INFO stats | grep -E 'total_net_input_bytes|total_net_output_bytes'

所有命令均匀变慢通常是带宽打满或跨 AZ(应扩容带宽、同 AZ 部署);丢包重传说明网络拥塞或 MTU 问题;连接被拒说明 maxclients 打满(调大或修连接池);连接超时需检查防火墙与安全组。

8.2 内核参数与 swap

需要设置的内核与配置项:vm.overcommit_memory = 1(允许内存过量分配,fork 必需)、net.core.somaxconn = 65535、redis.conf 中的 tcp-backlog 511、ulimit -n 65535。用 sysctl vm.overcommit_memory net.core.somaxconn 核对,用 grep VmSwap /proc/$(pgrep -f redis-server)/status 检查是否换页(如 VmSwap: 1258291 kB),并设 vm.swappiness=1。

vm.overcommit_memory = 0 时,fork 可能因「内存不足」失败(尽管实际有足够内存),导致 RDB 保存失败,这是 Redis 启动时最常见的告警之一。而 Redis 使用 swap 是灾难性的:被换出的页一旦被访问,会触发缺页中断,延迟瞬间达到毫秒甚至秒级。对策:maxmemory 设小、vm.swappiness 设为 1 或 0、物理内存留足余量。

8.3 客户端侧问题

连接池不足会表现为获取连接超时(增大池或减少等待);未设超时会让请求永久挂起(设置连接与读超时);大 value 传输让单请求耗时长(拆分或压缩);未用 Pipeline 会累积 RTT(批量命令走 Pipeline);阻塞式调用占满线程(改异步或加隔离);未设 CLIENT SETNAME 则无法定位来源。

import redis
pool = redis.ConnectionPool(
    host='redis-host', port=6379, max_connections=64,
    socket_timeout=1.0,           # 读超时
    socket_connect_timeout=0.5,   # 连接超时
    health_check_interval=30,
    client_name='app-order-service',
)
r = redis.Redis(connection_pool=pool)

8.4 跨 AZ 与跨区域

同 AZ 延迟约 0.10.3ms 最优;跨 AZ(同区域)约 0.52ms,常见但需注意主从复制流量费;跨区域 10100ms,只适合异步复制;公网 20200ms,生产禁用。应用与 Redis 必须在同一可用区:跨 AZ 部署的应用访问 Redis,每次请求多 1~2ms,在 10 万 QPS 下就是巨大的累积延迟。多 AZ 是为高可用(副本分布),不是为低延迟。


九、完整排障流程与案例复盘

9.1 标准排障流程

确认现象(全部命令还是特定命令、持续还是周期性、有无变更);分层定位(redis-cli --latency 测服务端基准,客户端侧测总延迟,差值即网络延迟);找慢命令(SLOWLOG GET 100、LATENCY HISTOGRAM、INFO commandstats 的 usec_per_call);找事件(先看 LATENCY DOCTOR,再看 LATENCY LATEST 与 HISTORY,关注 fork 与 aof 系列);看指标(INFO all 的关键字段);看客户端(CLIENT LIST 找 omem 大、idle 长的连接);看系统(CPU、内存、磁盘、网络、THP、swap);定位根因后用同样方法复测并记录到知识库。

9.2 案例一:周期性 50ms 尖刺

现象是每 5 分钟出现一次 p99 达 50ms 的尖刺,平均值正常。

redis-cli LATENCY DOCTOR
# fork: 48ms latency spike happened 12 times in the last hour.
redis-cli INFO stats | grep latest_fork_usec
# latest_fork_usec:48213
cat /sys/kernel/mm/transparent_hugepage/enabled
# [always] madvise never        <-- THP 开启

根因:每 5 分钟触发 RDB 快照,实例内存 12GB,THP 开启导致 fork 复制页表耗时 48ms。修复是把 THP 与 defrag 都设为 never,之后 latest_fork_usec 从 48213 降到 6200,尖刺消失。

9.3 案例二:某接口 p99 突然飙升

现象是订单服务的 Redis 调用 p99 从 1ms 升到 200ms,其他服务正常。

redis-cli SLOWLOG GET 20
# 1) 1) (integer) 31 2) (integer) 1696123456 3) (integer) 152340
#    4) 1) "KEYS" 2) "order:202609*" 5) "10.0.0.5:52341" 6) "app-order-service"

根因:订单服务新增了「按日期前缀查询订单」的功能,用了 KEYS order:202609*,在 200 万键的库上执行 152ms。修复是改用 SCAN 游标加 Pipeline 批量 MGET,并用 Set 维护日期索引:先 smembers("order:index:202609") 拿到 ID 列表,再一次性 mget 取回订单内容。

9.4 案例三:延迟随流量上升而恶化

现象是白天 QPS 上来后延迟从 0.5ms 升到 8ms,夜间恢复正常。

redis-cli INFO memory | grep -E 'used_memory_human|maxmemory_human|evicted_keys'
# used_memory_human:3.98G / maxmemory_human:4.00G / evicted_keys:2847392(持续淘汰)
redis-cli LATENCY LATEST
# 1) 1) "eviction-cycle" 3) (integer) 28 4) (integer) 156

根因:内存打满(3.98G/4.00G),每次写入都触发淘汰扫描,eviction-cycle 事件频繁。修复是 CONFIG SET maxmemory-policy allkeys-lfu、CONFIG SET maxmemory-samples 10、CONFIG SET activedefrag yes,并根治性地扩容或治理大 Key。

9.5 案例四:内存碎片导致的 RSS 暴涨

现象是 used_memory 稳定在 3GB,但 used_memory_rss 达 5.8GB,监控告警内存使用率 80%。根因是 mem_fragmentation_ratio:1.81,频繁写入删除不同大小的对象,jemalloc 产生大量无法复用的碎片。

redis-cli CONFIG SET activedefrag yes
redis-cli CONFIG SET active-defrag-ignore-bytes 100mb
redis-cli CONFIG SET active-defrag-cycle-min 5
redis-cli CONFIG SET active-defrag-cycle-max 75

碎片整理会消耗 CPU,active-defrag-cycle-max 控制单周期最大 CPU 占比,生产建议不超过 75,且应在低峰期观察效果。若碎片率持续大于 1.5 且整理无效,重启实例是最彻底的方案。

9.6 排障工具箱与告警阈值

工具箱:redis-cli --latency 与 --latency-histogram 测基准与分布;SLOWLOG GET 看慢命令;LATENCY DOCTOR 自动诊断;LATENCY HISTOGRAM 看命令级分布;INFO all 抓全量指标;CLIENT LIST 定位来源;CLIENT PAUSE 用于故障转移;--bigkeys 与 --memkeys 找大 Key;MONITOR 极短时观察命令流;iostat、sar、free 做系统层排查。

告警阈值建议:p99 延迟警告大于 5ms、严重大于 20ms;latest_fork_usec 警告大于 50ms、严重大于 200ms;mem_fragmentation_ratio 警告大于 1.5、严重大于 2.0;内存使用率警告大于 75%、严重大于 90%;blocked_clients 持续 1 分钟大于 0 即警告、大于 10 严重;rejected_connections 大于 0 即警告、持续增长严重;evicted_keys 增速每分钟大于 100 警告、大于 1000 严重;master_link_status down 10 秒警告、60 秒严重;连接数使用率大于 70% 警告、大于 90% 严重。


结语

Redis 延迟排障的核心不是记住多少命令,而是建立一套从表象到根因的收敛路径。核心要点回顾:

  1. 先分层再深入:用 --latency 与客户端侧对比,先确定问题在网络、客户端还是服务端
  2. LATENCY DOCTOR 是第一步:它把 fork、AOF、淘汰等事件诊断成人话,往往一眼就有方向
  3. SLOWLOG 有盲区:它只记录命令执行时间,不含网络传输与 fork 阻塞,必须与 LATENCY MONITOR 配合
  4. THP 是头号嫌疑:fork 尖刺十有八九与透明大页有关,自建环境必须关闭
  5. swap 是致命信号:mem_fragmentation_ratio < 1 说明已经换页,必须立即处理
  6. 大 Key 既是病因也是干扰:排查前先治理,扫描时务必控制节奏
  7. 集中过期要抖动:TTL 加 5%~10% 随机值,能消除周期性尖刺
  8. 纯缓存就关持久化:不需要的 fork 与 fsync 是延迟尖刺的常见来源
  9. CLIENT SETNAME 是基础设施:没有连接名的 CLIENT LIST 等于没有线索
  10. 同 AZ 部署是底线:跨可用区访问的 1~2ms 延迟在高 QPS 下会累积成灾难

延迟排障最忌讳的是「凭经验猜」。一个 50ms 的尖刺,可能是 fork、可能是 THP、可能是 swap、也可能是某个服务偷偷跑了 KEYS *。这些猜测的正确顺序应该由数据决定:LATENCY DOCTOR 告诉你 fork 有问题,SLOWLOG 告诉你是哪个服务、哪条命令,CLIENT LIST 告诉你连接来自哪里。让工具说话,而不是让直觉说话——这才是可复制的排障能力。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「redis」更多文章

  1. 云托管 Redis 选型与运维:ElastiCache、MemoryDB、Redis Cloud 与 Upstash 对比
  2. RedisTimeSeries 时序数据实战:降采样、压缩与监控告警
  3. RedisJSON 文档模型:JSONPath、路径更新与二级索引实战