跳到正文

Redis 监控指标与告警 ​

一句话:Redis 的监控不是把 INFO 抄一遍,而是按「资源→进程→服务→业务」四层找出最先变坏的那一环;它快在内存,所以故障几乎都从内存水位、fork 停顿和复制延迟开始,盯住这几个先兆,才能在 DB 被打穿之前动手。

适用版本:Redis 7.x / 8.x。INFO 字段与默认值以官方文档为准,6.0 之前的差异单独标注。

为什么需要 ​

Redis 在链路里通常只做一件事:替后端挡读。它变慢或不可用,压力不会消失,只会平移给 DB。更麻烦的是,Redis 的故障往往不是进程退出——进程还在,但内存满了、fork 卡了、主从断了,指标上只是几个数字缓慢变化。等业务侧报超时,DB 连接池通常已经被打满。所以监控要解决的是:在用户感知之前,看到哪个数字先不对。

核心机制 ​

四层观察面 ​

层看什么回答的问题
资源CPU、RSS、磁盘 IO/空间、网络、swap是不是机器先扛不住了
进程INFO memory/clients/stats/persistenceRedis 自己是否健康、是否在做重活
服务INFO replication、Sentinel、CLUSTER INFO高可用链路是否已经退化
业务命中率、P99 延迟、错误率、回源量用户是否已经受影响

排查从下往上:业务报警时先排除资源层,再看进程层有没有淘汰、fork 或阻塞,最后才怀疑服务层。反过来,服务层指标异常时业务层可能还没感觉,这正是提前处置的窗口。

资源层:先排除机器 ​

Redis 单线程执行命令,CPU 打满通常不是「算得多」,而是命令本身是 O(N)(KEYS、大 key 的 HGETALL),或 fork 后的 COW 在复制页表。内存要看 RSS 而不只是 used_memory:RSS 包含分配器碎片和 fork 期间的 COW 页,RSS 远高于 used_memory 时,容器更容易被 OOM Killer 杀。磁盘只在持久化和 AOF 重写时重要,但它慢会直接拖住写路径;网络看带宽和重传,集群模式还要看跨节点流量。

进程层:INFO 里的先兆 ​

  • 内存:used_memory 是分配器视角的逻辑用量,used_memory_rss 是操作系统视角的物理占用,maxmemory 是淘汰触发线。三者一起看,才能区分「数据真的多」和「碎片/COW 让 RSS 虚高」。evicted_keys 持续增长,说明已经在丢数据换空间,命中率下降只是时间问题。
  • 客户端:connected_clients 接近 maxclients 时新连接会被拒,rejected_connections 开始增长;blocked_clients 高说明大量客户端卡在 BLPOP、WAIT 这类阻塞命令上,通常是下游慢或锁等待。
  • 吞吐与延迟:instantaneous_ops_per_sec 掉零不一定是没流量,也可能是主线程被阻塞。latency 和 slowlog 回答「慢在哪条命令」,latest_fork_usec 回答「最近一次 fork 卡了多久」——fork 期间主线程停摆,这是 Redis 特有的延迟来源。
  • 持久化:rdb_last_bgsave_status 和 aof_last_write_status 不是 ok 就是硬故障,通常先于业务报错出现;rdb_changes_since_last_save 持续变大,说明快照一直没成功。
  • 缓存效果:keyspace_hits / (hits + misses) 是命中率。它没有绝对标准,要和自己的基线比;突然掉 10 个点,通常意味着批量过期、淘汰或热 key 消失。

服务层:主从、哨兵、集群 ​

  • 主从:master_link_status 为 down 时,master_link_down_since_seconds 才开始计时;恢复后如果 offset 差(主节点 master_repl_offset 与从节点 slave_repl_offset 之差)持续扩大,说明从节点追不上,不只是「断了一下」。sync_full 增长意味着发生了全量同步,会带来 fork、RDB 传输和带宽峰值。
  • 哨兵:INFO sentinel 看 master 的 status、slaves、sentinels,SENTINEL masters 看 quorum。主观下线(sdown)是单个哨兵的判断,客观下线(odown)才是多数派共识;只报 sdown 会产生大量误报。
  • 集群:cluster_state:ok、16384 个槽全覆盖、cluster_slots_pfail 和 cluster_slots_fail 为 0 才算健康。pfail 是疑似失联,先查网络和节点负载;fail 是已判定失败,要考虑槽迁移和副本接管。

两条典型的雪崩链路 ​

箭头方向就是预警顺序:内存水位和命中率斜率远早于 DB 承压,fork 耗时和延迟分位远早于连接数异常。

链路一:内存打满 → 淘汰 → 命中率下降 → 请求打到 DB。 写入持续增长,used_memory 顶到 maxmemory,evicted_keys 开始上涨。被淘汰的未必是最冷的 key,而是采样窗口里「看起来不热」的 key,热点也可能中招。命中率下降后,同样的请求穿透到 DB;DB 连接池被占满,接口超时,客户端重试又把流量放大。等 evicted_keys 报警时,DB 通常已经承压,真正的预警点是内存水位和命中率斜率。

链路二:fork/持久化/大 key → 延迟升高 → 客户端超时重试 → 连接与 CPU 进一步升高。BGSAVE 或 AOF 重写触发 fork,latest_fork_usec 飙升;fork 期间主线程暂停,COW 又让内存页翻倍。大 key 的删除或读取会让单条命令执行很久。客户端超时后重试,connected_clients 和 QPS 同时上涨,主线程更忙,延迟继续升高,形成正反馈。这条链路里 CPU 可能不高,但延迟和连接数会同时异常。

最小上手 ​

bash
# 进程层一次看全:内存、客户端、持久化、复制
redis-cli INFO
redis-cli INFO memory | grep -E "used_memory|maxmemory|mem_fragmentation"
redis-cli INFO stats | grep -E "evicted_keys|keyspace_hits|keyspace_misses|rejected_connections|latest_fork_usec"
redis-cli INFO clients | grep -E "connected_clients|blocked_clients"
redis-cli INFO replication | grep -E "master_link_status|master_repl_offset|slave_repl_offset"

# 延迟与慢命令
redis-cli --latency
redis-cli SLOWLOG GET 10

# 大 key / 热 key(SCAN 采样,都有额外开销,低峰执行)
redis-cli --bigkeys
redis-cli --hotkeys   # 需要 maxmemory-policy 为 LFU,否则直接报错
redis-cli CLUSTER INFO

Prometheus 侧用 redis_exporter 抓取(exporter 版本不同,指标名以官方文档为准):

yaml
scrape_configs:
  - job_name: redis
    static_configs:
      - targets: ["redis-exporter:9121"]
bash
docker run -d --name redis-exporter -p 9121:9121 \
  oliver006/redis_exporter -redis.addr redis://redis:6379

生产动作 ​

下面是一组起点阈值,必须按自己的基线校准,不要当成通用标准。

指标预警告警处置
used_memory / maxmemory> 75%> 90%查大 key 和增长最快的 key,扩容或调淘汰策略
evicted_keys 速率纯缓存实例持续 > 0快速上涨先扩容,再核对 TTL 与淘汰策略
命中率比 7 日基线低 5–10 个点低 10 个点以上查批量过期、热 key、淘汰
connected_clients / maxclients> 80%> 90% 或 rejected_connections > 0查连接泄漏与客户端连接池
blocked_clients明显高于基线持续上涨查阻塞命令与下游依赖
latency P99 / slowlog超基线 2 倍持续超基线且业务超时定位 O(N) 命令、大 key、fork
latest_fork_usec超过实例基线接近或超过业务超时时间关自动 RDB、错峰重写、拆小实例
rdb_last_bgsave_status / aof_last_write_status—非 ok立即查磁盘空间、权限、fork
master_link_status / offset 差down 超过 10sdown 超过 60s 或 offset 差持续扩大查网络、复制缓冲、从节点负载
cluster_state / slots_pfail / slots_failpfail > 0state 非 ok 或 fail > 0查节点存活、槽覆盖、迁移状态

主从、哨兵、集群的判断不能混:主从看「链路 + 追赶能力」,master_link_status 是通断,offset 差是追赶速度,sync_full 增长说明在反复全量同步;哨兵看「共识」,单个哨兵的 sdown 不算故障,quorum 决定能否判定 odown,真正切换还需要多数哨兵投票;集群看「槽」,节点活着但槽没覆盖,集群一样不可用。

处置顺序先保业务再查根因:内存和连接类问题先限流或扩容,持久化状态异常先确认磁盘,延迟问题先用 SLOWLOG 定位命令,再决定是否 kill 客户端或降级。

边界 ​

Redis 的强项是低延迟和简单数据结构,代价是内存贵、持久化弱、单线程怕慢命令。这决定了它适合做缓存和会话,不适合当唯一数据源;也决定了监控必须优先盯内存、fork、慢命令和复制延迟,而不是像磁盘数据库那样盯 IO 利用率。异步复制下切换丢最近写入是固有窗口,监控只能提前发现,不能消除。

维度适合不适合
数据量热数据能装进内存,GB 到百 GB 级全量数据远大于内存,靠 Redis 存主数据
一致性可接受异步复制和切换丢少量写要求强一致、零丢失的核心账务
查询形态按 key 点查、简单结构、计数和排行榜多条件关联、范围聚合、复杂事务
团队成本能维护主从/哨兵/集群并做容量规划没人盯内存和 fork,指望它自愈

还有几个容易误判的地方:

  • used_memory 与 used_memory_rss 的差值来自分配器碎片、COW 和页对齐,不能互相替代;容器里要以 RSS 对照内存 limit。
  • maxmemory 不包含副本输出缓冲、AOF 缓冲等开销,「没到 maxmemory」不等于「不会 OOM」。
  • 阈值随业务变化:延迟敏感业务和离线缓存的警戒线完全不同,表里的数字只是起点。
  • MONITOR 会把每条命令复制给监控连接,开销大且可能泄漏敏感数据,不能常开;--bigkeys/--hotkeys 走 SCAN 或依赖 LFU,也有开销,放低峰执行。
  • 采集本身有成本:INFO 很轻,但高频 SCAN、大数量 SLOWLOG GET 和 exporter 的全量采集都会增加主线程负担;采样间隔太长又会漏掉尖刺。

相关:04-内存管理、03-持久化、06-主从复制、07-哨兵模式、08-集群模式、10-大Key问题、11-热点Key问题、99-生产检查清单。

讲清楚 ​

Redis 监控的核心不是指标数量,而是分层定位:资源层排除机器,进程层看内存、fork、连接和慢命令,服务层看复制与集群共识,业务层确认用户是否已经受影响。Redis 快在内存、弱在持久化和单线程,所以典型雪崩只有两条:内存打满后淘汰把命中率打下去,请求回源压垮 DB;fork、持久化或大 key 把延迟拉高,客户端重试再放大连接和 CPU。预警要放在内存水位、命中率斜率和 fork 耗时上,而不是等业务超时。阈值只是起点,必须按自己的基线和业务超时校准。

把一门技术讲透到既懂也会用