Redis内存淘汰策略,maxmemory
Redis 内存打满后如果没设淘汰策略,写入会直接报 OOM 错误。
解决方法是配置 maxmemory 上限和 maxmemory-policy 淘汰规则。
本文从零开始,带你完成策略选择、配置修改、动态生效和效果验证,适合刚接触 Redis 的运维或开发人员。
先搞清楚 Redis 什么时候会淘汰数据
Redis 是内存数据库,所有数据放在内存里。
当内存使用量达到 maxmemory 设定的阈值时,Redis 就会根据 maxmemory-policy 决定:是拒绝写入,还是淘汰一部分旧数据腾出空间。
没有配置 maxmemory 时,淘汰策略不会生效,Redis 会一直申请内存直到系统 OOM。
所以配置淘汰策略前,必须先设置 maxmemory。
常用淘汰策略含义如下:
noeviction:不淘汰任何数据,内存满时写入命令报错,读命令正常。allkeys-lru:从所有 key 中淘汰最近最少使用的。allkeys-lfu:从所有 key 中淘汰访问频率最低的(Redis 4.0+)。allkeys-random:从所有 key 中随机淘汰。volatile-lru:只从设置了过期时间的 key 中淘汰最近最少使用的。volatile-lfu:只从设置了过期时间的 key 中淘汰访问频率最低的。volatile-random:只从设置了过期时间的 key 中随机淘汰。volatile-ttl:只从设置了过期时间的 key 中淘汰剩余存活时间最短的。
如果所有 key 都没有设置过期时间,volatile-* 系列策略会退化成 noeviction 行为,写入同样会报错。
配置前需要确认的两件事
动手改配置之前,先确认当前 Redis 版本和内存使用情况,避免改错方向。
查看版本:
redis-server --version
查看当前内存和策略:
redis-cli info memory | grep -E "used_memory_human|maxmemory_human|maxmemory_policy"
如果 maxmemory_human 显示 0B,说明还没有设置内存上限,需要先设置。
修改 maxmemory-policy 的两种方式
方式一:修改配置文件永久生效
找到 Redis 配置文件,通常路径是 /etc/redis/redis.conf 或 /etc/redis/6379.conf。
用编辑器打开:
sudo vim /etc/redis/redis.conf
找到或添加以下两行:
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory 根据服务器实际内存设置,建议留出 30% 左右给系统和其他进程。allkeys-lru 适合纯缓存场景,所有 key 都可以被淘汰。
保存后重启 Redis:
sudo systemctl restart redis
方式二:运行时动态修改
不想重启服务,可以用 CONFIG SET 动态调整:
redis-cli config set maxmemory 2gb
redis-cli config set maxmemory-policy allkeys-lru
动态修改在重启后会失效,建议同时写入配置文件。
策略选不对会踩哪些坑
缓存场景用了 noeviction:
内存满后所有写入报错 OOM command not allowed when used memory > 'maxmemory',
业务直接受影响。
持久化数据用了 allkeys-lru:没设过期时间的重要数据也可能被淘汰,导致数据丢失。
这类场景建议用 volatile-lru 并给临时数据设置过期时间。
maxmemory 设得太大:接近物理内存上限,触发系统 OOM Killer 杀掉 Redis 进程,比淘汰数据更严重。
从库淘汰策略与主库不一致:主从复制时可能引发数据不一致,建议主从使用相同策略。
配置后如何验证生效
执行以下命令查看当前策略和内存上限:
redis-cli config get maxmemory
redis-cli config get maxmemory-policy
预期输出:
1) "maxmemory"
2) "2147483648"
1) "maxmemory-policy"
2) "allkeys-lru"
再查看淘汰统计:
redis-cli info stats | grep evicted_keys
evicted_keys 数值大于 0,说明已经发生过淘汰,策略正在工作。
如果持续增长且业务无异常,说明配置合理。
常见疑问
maxmemory 应该设置多大?
建议设置为物理内存的 50% 到 70%,同时考虑是否开启 RDB 持久化。
如果开启 RDB,fork 子进程会额外占用内存,需要预留更多空间。
allkeys-lru 和 volatile-lru 怎么选?
如果 Redis 只做缓存,所有数据都可以丢,选 allkeys-lru。
如果部分数据需要持久保留,给临时数据设置过期时间,选 volatile-lru。
淘汰策略会影响性能吗?
LRU 和 LFU 需要维护额外数据结构,会有轻微开销。
Redis 采用近似 LRU 算法,通过采样实现,对性能影响很小,可以放心使用。
设置后还需要监控什么?
重点关注 evicted_keys 增长速度和 used_memory 曲线。
如果淘汰频繁但命中率下降明显,说明内存偏小,需要考虑扩容或优化数据结构。
配置完成后,建议先在测试环境验证淘汰行为,再应用到生产环境。
遇到写入报错时,优先检查 maxmemory 和 maxmemory-policy 是否匹配当前业务场景。