Redis 内存打满导致写入失败排查实战:从内存统计到逐出策略的五步流程

举报
yd_229207802 发表于 2026/11/10 10:54:30 2026/11/10
【摘要】 线上业务高峰期,应用向 DCS for Redis 写入时大面积报 OOM,本文沿内存统计、大 Key、逐出策略的链路定位根因,并给出应急止血与根治的五步流程。

背景

线上业务高峰期,应用向华为云 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、容量拆分与监控把问题挡在下一次之前。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。