必须显式设置maxmemory,否则所有淘汰策略均不生效;Redis默认maxmemory为0(无限制),即使配置volatile-lru等策略,也会因未达触发条件而持续占用内存直至被OOM Killer终止。

必须显式设置 maxmemory,否则所有淘汰策略都不生效。 Redis 默认不设内存上限(64 位系统下 maxmemory 为 0),哪怕你配了 volatile-lru,只要没设 maxmemory,Redis 就永远不会触发淘汰——它只会一直吃内存,直到被系统 OOM killer 杀掉。
maxmemory 怎么设才靠谱
不能只看业务数据量,used_memory 统计的是整块内存开销,包括:
- 键值本身 + 过期字典
- 主从复制缓冲区(
repl-backlog-size,默认 1MB,大流量下建议调到 32–64MB) - 客户端输出缓冲区(尤其长连接、
MONITOR、大 payloadSCAN会快速堆积) - AOF 重写缓冲区、Lua 脚本缓存
实操建议:
- 先用
INFO memory观察高峰时的used_memory峰值,不是平均值 - 在纯数据估算基础上,乘以 1.5–2 的安全系数(比如预估数据占 3GB,至少设
maxmemory 6gb) - 32 位 Redis 实例最大只能设到 ~3GB,这不是配置问题,是地址空间硬限制
volatile-lru 和 allkeys-lru 到底选哪个
关键区别不在“LRU”上,而在“volatile-”前缀是否成立:它只对设置了 EXPIRE 的 key 生效。如果你的 session、token、验证码等都带 TTL,但商品详情、配置项、用户基础信息等是永久 key,那就必须用 volatile-lru;否则 allkeys-lru 会把永久 key 也踢出去,导致核心数据丢失。
常见误配场景:
- 用
allkeys-lru缓存混合型数据 → 热点永久 key 被误删 - 用
volatile-lru但大量 key 没设 TTL → 实际无 key 可淘汰,写入直接报OOM command not allowed when used memory > maxmemory - 压测时一切正常,上线后因部分 key 忘记加
EXPIRE,淘汰失效
LRU 不是真 LRU,LFU 有衰减,别信直觉
Redis 的 volatile-lru 和 allkeys-lru 都是近似算法:每次淘汰时随机采样 maxmemory-samples 个 key(默认 5),挑其中 lru 字段最旧的删。采样数越大越准,但代价是 CPU 开销上升。生产环境可试 maxmemory-samples 10,但别盲目拉到 20+。
volatile-lfu / allkeys-lfu 同理:频率计数器会随时间衰减(避免历史访问长期影响决策),且同样基于采样。如果你的访问模式是“短时爆发 + 长期沉寂”,LFU 可能比 LRU 更稳;但如果冷热切换快,LFU 的衰减延迟反而会导致误判。
验证是否生效最简单的方法:
- 起一个测试实例,配好
maxmemory 100mb和maxmemory-policy volatile-lru - 批量写入带 TTL 的 key:
SET key:1 value EX 3600,直到触发淘汰(INFO stats看evicted_keys是否增长) - 用
OBJECT IDLETIME key:xxx查看剩余 key 的空闲时间,确认淘汰倾向是否符合预期
真正容易被忽略的点是:淘汰发生在每次写命令执行前,但清理动作本身不阻塞请求;而过期 key 的惰性删除和定期删除是另一套逻辑——它们共存,但互不替代。所以即使你用了 volatile-ttl,也不能指望它“提前清掉快过期的 key”来腾空间,它只在内存超限时才参与淘汰决策。


















