必须同时设置 maxmemory 和 maxmemory-policy noeviction;仅设 maxmemory 而未显式配置正确策略(如拼写错误或大小写错误),redis 会退回到默认行为,不触发淘汰,导致内存持续增长直至触发系统 oom killer 杀死进程。

必须同时设置 maxmemory 和 maxmemory-policy noeviction,缺一不可;只设一个或拼写错误(如 no-eviction)会导致策略不生效,Redis 仍可能被系统 OOM Killer 杀掉。
为什么只配 maxmemory 还会 OOM
Redis 的 maxmemory 是个“开关阀”,但不是“保险丝”:它只在淘汰策略启用时才参与内存水位判断。如果没配 maxmemory-policy,或者配了但拼错(比如写成 noeviction 带空格、NoEviction大小写混用),Redis 会退回到默认行为——低版本是 volatile-lru,高版本虽默认 noeviction,但你不显式声明就等于把控制权交给版本和运气。
更危险的是:即使你写了 maxmemory 2gb,但没设策略,Redis 实际上不会拒绝写入,而是继续接收数据,直到 RSS 内存爆满,触发 Linux 的 OOM Killer 直接干掉进程。
验证方式很简单:
- 执行
redis-cli CONFIG GET maxmemory-policy,必须返回noeviction(全小写、无空格) - 执行
redis-cli INFO memory | grep used_memory,确认used_memory接近但不超过你设的maxmemory值 - 若
evicted_keys在持续增长,说明策略根本不是noeviction
怎么让配置真正持久化不丢失
CONFIG SET 只影响当前运行实例,重启即失效。生产环境必须落盘。
推荐操作顺序:
- 编辑
redis.conf,添加两行(位置不限,但建议放在MEMORY LIMIT区块):maxmemory 2gbmaxmemory-policy noeviction - 执行
redis-cli CONFIG REWRITE—— 它会自动重写配置文件,保留注释和结构,比手动改更安全 - 不要直接 kill -9 后重启;先
redis-cli SHUTDOWN SAVE,再启 - 重启后立刻验证:
redis-cli CONFIG GET maxmemory和CONFIG GET maxmemory-policy
注意:CONFIG REWRITE 不会覆盖你手动加的注释,但会删掉语法错误或无效配置行,所以改完要检查。
应用层怎么正确捕获并响应 OOM 错误
启用 noeviction 后,所有写命令失败时返回标准错误:(error) OOM command not allowed when used memory > 'maxmemory'。这不是网络异常,是 Redis 主动拒绝。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
常见客户端表现:
- Python
redis-py:抛redis.exceptions.ResponseError,str(e)含上述字符串 - Node.js
ioredis:抛ReplyError,e.message字段匹配该字符串 - Go
github.com/go-redis/redis/v8:err.Error()包含该提示
关键动作:
- 不能忽略或静默吞掉这个错误——否则业务以为写成功了,实际数据丢了
- 需记录日志 + 上报监控(比如 Prometheus 抓
redis_errors_total{type="oom"}) - 降级逻辑要明确:比如切只读、走 DB 回源、返回兜底值、或限流拦截后续请求
别依赖 evicted_keys 监控——它在 noeviction 下恒为 0,毫无意义。
真实内存远超 maxmemory 的隐性开销
maxmemory 限制的是 used_memory,即键值对本身占用,但它不统计:
- Lua 脚本执行期间生成的临时对象
- 客户端输出缓冲区(尤其 pub/sub 订阅者积压或 big key scan)
- AOF rewrite 或 RDB fork 子进程的内存副本(可能瞬间翻倍)
所以,即使 used_memory 显示刚到 2GB,RSS 可能已到 3GB+,系统 OOM Killer 照样出手。
安全做法:
- 把
maxmemory设为机器总内存的 45%–60% - 例如 16GB 机器,
maxmemory 6gb是较稳妥的上限 - 用
INFO clients查client_longest_output_list,发现异常积压及时处理
最常被跳过的一步:上线前没跑 redis-cli --stat 观察高峰期 RSS 增长趋势,结果压测时才发现 jemalloc 碎片率飙到 1.8,真实内存比 used_memory 高出近一倍。










