Redis 内存打满导致写入失败排查实战:从内存统计到逐出策略的五步流程
背景
线上业务高峰期,应用向华为云 DCS for Redis 写入时突然大面积报错,返回 OOM command not allowed when used memory > 'maxmemory',缓存写入与队列入队同时失败。本文记录一次真实排查过程:从内存统计入手,先确认是“写满了”还是“用歪了”,再沿着逐出策略、过期键、大 Key 的链路定位根因,最后给出可复用的五步流程。
第一步:确认内存是否真的打满
先看实例内存水位与淘汰指标,区分“内存不足”和“连接或命令异常”:
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio|evicted_keys|expired_keys"
重点看三个值:used_memory 与 maxmemory 的比值是否接近 1;evicted_keys 是否在持续增长(说明逐出正在发生,内存已触顶);mem_fragmentation_ratio 是否远大于 1(内存碎片偏高,实际可用比账面更少)。
第二步:找出吃掉内存的 Key
内存打满通常不是均匀增长,而是少数 Key 膨胀,或者海量小 Key 堆积。用 --bigkeys 快速扫描,再用 MEMORY USAGE 核对嫌疑 Key:
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning --bigkeys
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning MEMORY USAGE "user:session:10086"
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning INFO keyspace
--bigkeys 只能看到体积最大的几类键;如果怀疑是海量小 Key,对照 INFO keyspace 的键数量级,分库按模式抽样核对。
第三步:核对过期键与逐出策略
如果内存里堆了大量本应过期的 Key,问题出在过期或逐出配置。先确认当前策略:
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning CONFIG GET maxmemory-policy
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning INFO stats | grep -E "evicted_keys|expired_keys|keyspace_hits|keyspace_misses"
三个常见坑:策略是 noeviction,内存一满就直接拒绝写入,业务立即报错,这是本次故障的直接原因;二是业务把不该缓存的数据也写进来且不设 TTL,Key 只增不减;三是大量 Key 的 TTL 被业务不断续期,过期键始终释放不掉。
第四步:应急止血,让写入先恢复
根因还没查完之前,先恢复写入:
# 1. 清理明确可丢弃的历史缓存 Key(按前缀,逐批删除)
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning --scan --pattern "temp:*" | xargs -L 100 redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning DEL
# 2. 把逐出策略临时改为 allkeys-lru,优先淘汰最久未使用的数据
redis-cli -h <Redis实例地址> -p 6379 -a <密码> --no-auth-warning CONFIG SET maxmemory-policy allkeys-lru
注意:CONFIG SET 只在当前实例进程内生效,重启后失效,事后要在控制台把 maxmemory-policy 改为期望值并持久化。删除数据前先备份关键 Key 列表,误删不可恢复;清理时用小批量,避免大批量删除阻塞实例。
第五步:根治——容量与策略双管齐下
应急之后做三件长效的事:给所有缓存数据设定合理的 TTL,避免无过期时间的 Key 持续累积;按业务把内存拆分到独立实例或数据库编号,避免一个坏 Key 拖垮全实例;在云监控上对内存使用率(建议 75%)与 evicted_keys 增速设置告警,把“内存打满”的发现时间从“用户先投诉”提前到“告警先响起”。
总结
Redis 写入失败不一定是 Redis 本身坏了,多数时候是内存到了上限而逐出策略兜不住。排查记住五步:先看内存水位,再找内存大户,然后核对过期与逐出策略,接着应急止血让写入恢复,最后用 TTL、容量拆分与监控把问题挡在下一次之前。
- 点赞
- 收藏
- 关注作者
评论(0)