
线上 Redis 的 used_memory 一路上涨、最终触发 maxmemory 淘汰或 OOM,是常见故障。本文给出一套从“看全局指标”到“定位具体 key”的排查流程,命令均为 Redis 原生命令,云上托管实例与自建实例通用(托管实例部分命令可能被限制,以控制台说明为准)。
redis-cli INFO memory重点关注字段:
used_memory:Redis 分配器向系统申请的内存,即数据集及内部结构占用。used_memory_rss:操作系统视角的常驻内存。mem_fragmentation_ratio:rss / used_memory。明显大于 1.5 说明碎片较多;小于 1 说明发生了 swap,需要立即处理。maxmemory、maxmemory_policy:上限与淘汰策略。策略为 noeviction 时写满会直接报错。redis-cli MEMORY DOCTOR
redis-cli MEMORY STATSMEMORY DOCTOR 会给出可读的诊断建议,MEMORY STATS 可看到各类内部开销占比。
redis-cli --bigkeys -i 0.1--bigkeys 基于 SCAN,按类型输出最大的 key;-i 0.1 表示每次扫描间隔 0.1 秒,降低对线上的影响。Redis 4.0 及以上还可以直接查看单个 key 的内存:
redis-cli MEMORY USAGE user:session:10086 SAMPLES 5对 hash、list、set 等集合类型,SAMPLES 越大越准、越耗时。
处理大 key 的原则:
UNLINK 代替 DEL,由后台线程释放内存,避免主线程阻塞。HGETALL、SMEMBERS 大集合,改用 HSCAN、SSCAN。内存涨而 key 数量也涨,往往是 key 没设置 TTL。
redis-cli INFO keyspace
# db0:keys=5230000,expires=12000,avg_ttl=3600000keys 远大于 expires 说明大量 key 永不过期。可抽样检查:
redis-cli --scan --pattern 'cache:*' | head -n 20 | xargs -I{} redis-cli TTL {}返回 -1 即无过期时间。修复方式是在写入处统一带上过期时间,例如 SET key value EX 3600,不要先 SET 再 EXPIRE,两步之间失败会留下永久 key。
另外 Redis 采用“惰性删除 + 定期抽样删除”,过期 key 不会立刻释放;如果大量 key 在同一时刻过期,可以给 TTL 加随机抖动,避免集中过期造成的延迟尖刺。
当 mem_fragmentation_ratio 长期偏高且 used_memory 并不大时,可以开启在线碎片整理(需要 Redis 使用 jemalloc 编译):
redis-cli CONFIG SET activedefrag yes
redis-cli INFO memory | grep -E 'active_defrag|allocator_frag'在线整理会占用一定 CPU,建议在低峰开启并观察延迟。如果碎片严重且可以接受主从切换,也可以通过重启从库、再切换的方式整理。
used_memory / maxmemory 设置分级告警(如 80%、90%)。evicted_keys、expired_keys:evicted_keys 持续增长说明已经在淘汰数据。--bigkeys,把结果与上周对比。INFO memory 看 used_memory、碎片率、maxmemory_policy。INFO keyspace 对比 keys 与 expires。--bigkeys / MEMORY USAGE 定位大 key,拆分并改用 UNLINK。内存问题很少是单一原因,多数是“大 key + 无 TTL + 缺少监控”叠加。按上面顺序逐层排除,通常能在半小时内定位到根因。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。