半夜被内存告警叫醒
Redis 实例内存从 4G 一夜之间冲到 14G,触发了 maxmemory 限制开始淘汰 key,部分缓存击穿打到数据库,数据库 CPU 跟着飙到 90%。我登录上去按几个维度逐一排查,过程比想象的有条理。Redis 内存暴涨不是玄学,按固定顺序查基本能覆盖绝大多数情况。
先看是不是 bigkey
用 redis-cli 自带的分析,扫一遍找出占用异常的大 key:
redis-cli --bigkeys -i 0.01
# 输出节选
[00.12%] Biggest string found 'session:user:8842' has 12.3M
[03.40%] Biggest hash found 'cart:shop:9921' has 48000 fields
发现一个购物车 hash 被塞了 4.8 万字段,是正常的一百倍——上游批量写入时没做分页,一次 hset 全量覆盖反而累积出超大 key。这种 key 删除时还会阻塞主线程,得用 UNLINK 异步删,千万别 DEL。
客户端缓冲区
bigkey 之外,还得看输出缓冲区是不是被慢消费者撑爆。有个报表服务订阅了 keyspace 通知但消费极慢,积压全在 Redis 端:
redis-cli info clients
# client_recent_max_output_buffer: 2104857600 # 2GB!
某个 client 的输出缓冲区占了 2G。解决方案是给订阅类客户端设 client-output-buffer-limit,超了就断连,避免一个慢消费者拖垮整实例。我们把它配成 256MB 硬上限,超了就踢,宁可断这个连接也不让全实例受影响。
内存碎片率与副本积压
info memory 里看碎片率:
mem_fragmentation_ratio: 1.02 # 接近 1,碎片正常
这次碎片率正常,排除碎片问题。再看副本:
redis-cli info replication
# repl_backlog_size: 1048576 # 1MB,太小
# 主从断连后重同步要全量,瞬间吃内存
把 repl_backlog_size 调到 256MB,避免频繁全量重同步带来的内存尖刺。主从网络抖动时这点尤其重要,否则一断一连就是一次全量 RDB,内存瞬间翻倍。
留个问题
关于《Redis 内存突然暴涨的排查思路》里这个坑,你当时是怎么处理的?欢迎在评论区聊聊你踩过的类似情况。