土法炼钢兴趣小组的算法知识备份

【Redis / 缓存内核】生产排障:大 key · fork · 慢日志与可复现清单

文章导航

分类入口
databasestorage
标签入口
#redis#troubleshooting#slowlog#latency-doctor#big-key#fork#fragmentation#lazyfree#blocking-commands#7.4

目录

P99 突然从毫秒跳到秒级,监控上 CPU 不高、网络也正常——常见根因不是「Redis 挂了」,而是 主线程被单条命令或 fork 拖住。第 2 篇讲过主线程执行命令;第 9–11 篇讲过 fork 与 AOF rewrite;第 12 篇讲过复制全量同步。本篇把这些 合成可执行的排障路径:先读信号,再对照机制,最后用 可复现命令 验证假设(本环境未安装 redis-server 时,只给出命令与预期观察维度,不伪造 INFO 数字)。

本文是「Redis / 缓存内核」系列第 15 篇(共 16 篇)。→ 系列目录

版本锚定:Redis OSS 7.4 / 8.x;官方 Latency monitoringSLOWLOGMEMORY` 子命令文档。


一、排障总览:先分「阻塞主线程」还是「资源外因」

flowchart TD
  S["Symptom: latency spike / timeout"] --> Q1{"Redis CPU high on main thread?"}
  Q1 -->|yes| B["Blocking cmd / big key / O(N) scan"]
  Q1 -->|no| Q2{"fork or disk IO?"}
  Q2 -->|yes| F["BGSAVE / AOF rewrite / replication full sync"]
  Q2 -->|no| Q3{"Memory pressure?"}
  Q3 -->|yes| M["eviction / fragmentation / OOM"]
  Q3 -->|no| N["network / client pool / Cluster MOVED storm"]
信号来源 看什么 机制锚点
SLOWLOG GET 慢命令名、参数规模、耗时 主线程单线程执行
LATENCY DOCTOR / LATENCY GRAPH 事件类型(fork、aof_write、expire) 官方 latency 框架
INFO commandstats usec_per_call 异常的命令 热路径命令
INFO persistence rdb_bgsave_in_progressaof_rewrite_in_progress fork 子进程
INFO replication master_link_statussync_full 全量同步
MEMORY DOCTOR / MEMORY STATS 碎片率、db.overage 分配器与编码
redis-cli --bigkeys / MEMORY USAGE key 大 key 尺寸 网络与延迟放大

二、大 key:延迟、迁移与复制的共同放大器

大 key 指单键值或聚合类型元素过多导致:单命令 \(O(N)\) 过长、序列化/RDB/AOF 膨胀、Cluster MIGRATE 与复制回放卡顿。

诊断命令(在 测试实例 上执行;生产先用 SCAN 采样):

# 扫描可能的大 key(对线上有负载,建议在从库或低峰跑)
redis-cli --bigkeys

# 单 key 精确内存(含编码开销)
redis-cli MEMORY USAGE mykey SAMPLES 5

# 集合类元素个数
redis-cli SCARD myset
redis-cli HLEN myhash
redis-cli XLEN mystream

治理方向(与机制一致,非穷尽):


三、fork 延迟:持久化与复制的隐形尖刺

BGSAVEBGREWRITEAOF、复制全量同步均可能 fork() 子进程。Linux 上写时复制使 父进程在 fork 期间 可能遭遇显著延迟(页表复制、内存越大越明显),表现为客户端超时,而 CPU 未必持续高。

观察命令:

redis-cli INFO persistence | egrep 'rdb_|aof_'
redis-cli INFO stats | grep instantaneous_ops_per_sec
redis-cli LATENCY DOCTOR
redis-cli LATENCY GRAPH fork

缓解思路(配置层,需结合 SLO):

本机复现 fork 敏感度(仅实验环境):启动独立 redis-server,灌入大数据集后手动 BGSAVE,同时对另一终端跑 redis-cli --latencyLATENCY GRAPH fork,观察延迟尖刺是否与 fork 事件对齐——具体毫秒数依赖机器内存与内核版本,此处不写入虚构输出


四、阻塞命令与 O(N) 陷阱

下列命令在 主线程 执行且可能长时间占用(官方命令文档均标注复杂度):

命令 / 模式 风险
KEYS 全局扫描,生产禁用
FLUSHALL / FLUSHDB 同步删除大量 key
SUNION / SORT(大集合) \(O(N)\) 或更大
SAVE(非 BG) 阻塞至 RDB 完成
BLPOP 等阻塞列表 阻塞 客户端连接,不阻塞其他客户端命令执行(易与主线程阻塞混淆)
DEBUG 系列 仅调试
# 查看最近慢命令(条目数依 slowlog-log-slower-than 配置)
redis-cli SLOWLOG GET 20
redis-cli CONFIG GET slowlog-log-slower-than
redis-cli CONFIG GET slowlog-max-len

# 命令级累计耗时
redis-cli INFO commandstats

LATENCY MONITOR 需显式开启(有开销):

redis-cli CONFIG SET latency-monitor-threshold 100
redis-cli LATENCY LATEST
redis-cli LATENCY HISTORY fork

五、内存碎片与 maxmemory 误判

INFO memoryused_memory_rss 显著大于 used_memory 时,可能存在 碎片分配器持有页。Redis 4.0+ 提供 ACTIVE DEFRAG(需配置开启)在线整理;代价是额外 CPU。

redis-cli INFO memory
redis-cli MEMORY STATS
redis-cli MEMORY DOCTOR
redis-cli CONFIG GET activedefrag

勿把 eviction第 8 篇)与 fragmentation 混谈:前者是策略淘汰 key,后者是 空闲页无法重用maxmemory 达到上限但 RSS 仍高时,两条线都要查。


六、Cluster 与复制相关延迟

现象 检查
间歇 -MOVED / -ASK 风暴 客户端是否 Cluster-aware;是否正在 resharding
读 replica 陈旧 INFO replicationslave_repl_offset 与 master 差值
全量同步 sync_full 增长、master_link_status:down
redis-cli CLUSTER INFO
redis-cli CLUSTER NODES
redis-cli INFO replication

七、可复现清单(测试环境最小步骤)

以下步骤假设本机已安装 Redis 7.4+;若无,跳过执行,仅作排障模板。

A. 慢命令留痕

redis-server --port 6379 --daemonize yes
redis-cli CONFIG SET slowlog-log-slower-than 1000
redis-cli DEBUG POPULATE 100000 foo 100
redis-cli KEYS 'foo*'
redis-cli SLOWLOG GET 5
redis-cli DEBUG POPULATE 0

B. 大 key 扫描

redis-cli DEBUG POPULATE 1 bigkey 100000
redis-cli --bigkeys
redis-cli MEMORY USAGE bigkey:0

C. Latency 与 fork(需一定内存才有感)

redis-cli CONFIG SET latency-monitor-threshold 1
redis-cli BGSAVE
redis-cli LATENCY LATEST
redis-cli LATENCY GRAPH fork

D. 碎片观察(长跑后更有意义)

redis-cli INFO memory
redis-cli MEMORY DOCTOR

验证通过标准:命令能跑通;你能把观察到的现象(慢命令名、latency 事件类型、是否 bgsave_in_progress)对应到上文机制——而非对齐某一组虚构毫秒值。


八、常见误解

误解 事实
「CPU 低就不是 Redis 问题」 fork、磁盘 fsync、客户端连接打满都可导致超时且 CPU 不高
「上 SSD 就没有 AOF 问题」 fsync 语义与 rewrite 仍可能阻塞或放大延迟(fsyncgate)
UNLINK 永远异步」 极小 key 仍可能同步路径;大 key 依赖 lazyfree-lazy-user-del 等配置
「SLOWLOG 为空就没事」 阈值以上才记录;P99 恶化可能来自 未超阈值的大量 5ms 命令
「MEMORY DOCTOR 一行就能修」 它给建议方向;是否 activedefrag 需评估 CPU 与版本

九、学术谱系、争论与开放问题

谱系:Google Why is my database slow 类经验 → Redis 内置 Latency Monitoring(antirez 博客,B 级)→ 云托管可观测(外部产品,本篇不展开)。

争论:在线 activedefrag vs 重启换页;no-appendfsync-on-rewrite 的丢失窗口是否可接受——取决于 RPO,无社区统一答案。

开放问题


十、小结

三句话小结

  1. Redis 排障先分 主线程阻塞(大 key、O(N)、阻塞命令)与 fork/IO/复制 外因,用 SLOWLOGLATENCYINFO 对齐机制而非猜。
  2. 大 key 同时伤害延迟、持久化、Cluster 迁移与复制;治理靠拆分、UNLINK、禁止 KEYS,不是单纯加内存。
  3. 本篇命令清单可在测试实例复现;生产数字必须来自你自己的运行结果,不要套用文章里的虚构 INFO 片段。

下一篇收束全系列:选型与阅读地图


参考资料

文档(A 级)

  1. Redis Documentation, Latency monitoringLATENCY DOCTORLATENCY GRAPH)。
  2. Redis Documentation, DebuggingMemory optimizationMEMORY DOCTOR--bigkeys)。
  3. Redis Commands, SLOWLOGINFOUNLINKSCAN
  4. Redis OSS 7.4 src/latency.csrc/debug.cDEBUG POPULATE 仅测试)、src/lazyfree.c

辅助(B 级)

  1. RDBAOF复制
  2. fsync 失败真相

返回 系列目录 | 上一篇:Memcached 对照 | 下一篇:选型与阅读地图

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .