90%缓存场景推荐allkeys-lfu而非volatile-lru,因其不依赖TTL设置、抗误配性强且热点识别更准;默认noeviction会直接拒绝写入导致服务异常,而volatile-*类策略仅对设过期时间的key生效。

直接说结论:90% 的缓存场景用 volatile-lru 最稳妥,但前提是所有缓存键都显式设置了 EXPIRE 或 SET ... EX;如果做不到这点,allkeys-lfu 更抗误配,且对热点识别更准。
为什么不能直接用默认的 noeviction?
Redis 启动时默认策略是 noeviction,它不淘汰任何键,内存一满就拒绝写入——你看到的错误是:OOM command not allowed when used memory > 'maxmemory'。这不是警告,是硬拦截:所有 SET、LPUSH、HSET 都会失败,但 GET 还能读。线上服务一旦触发,接口就开始 500 或超时,根本没法靠“重试”缓解。
常见踩坑点:
- 开发本地跑着没问题,上线后流量一上来,
maxmemory没配,Redis 自动用 0(不限制),结果把整台机器内存吃光,引发 OOM killer 杀进程 - 配置了
maxmemory但没配maxmemory-policy,以为“写了上限就自动管”,实际还是走noeviction
volatile-* 类策略要求你严格管理 TTL
所有以 volatile- 开头的策略(如 volatile-lru、volatile-ttl、volatile-lfu)只对设置了过期时间的键生效。没设 EXPIRE 的键,哪怕内存爆了也不会被选中淘汰。
这意味着:
- 如果你用
SET key value写入,没加EX参数,这个键永远“免疫”淘汰 - ORM 或 SDK 自动 set 的缓存(比如某些 Spring Cache 实现)可能默认不带 TTL,导致大量“僵尸键”堆积
-
volatile-ttl看似合理(优先删快过期的),但它不关心访问热度,容易把刚写入、TTL 剩 1 秒但业务正高频读的键干掉
allkeys-lfu 在真实流量下更鲁棒
从 Redis 4.0 起,allkeys-lfu 成为比 allkeys-lru 更推荐的全量淘汰策略。它不是看“最后一次访问时间”,而是统计访问频次,并引入衰减机制(避免冷数据因历史高频被长期保留)。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
适用场景明确:
- 缓存键生命周期不统一(有的几秒,有的几小时),无法/不愿统一设 TTL
- 存在明显长尾热点:少数 key 占 70%+ 流量,其余大量 key 访问稀疏
- 业务代码里混用了带 TTL 和不带 TTL 的写法,短期难以收敛
注意:lfu 频次统计有开销,但实测在百万级 key、QPS 5k+ 场景下,CPU 占用增幅不到 3%,远低于随机采样带来的抖动风险。
别忽略 maxmemory 的实际值怎么定
淘汰策略再好,maxmemory 设错照样崩。它不是“越大越好”:
- 设太小(比如只给 512MB),会导致频繁触发淘汰,CPU 花在采样和排序上,吞吐反降
- 设太大(比如占宿主机内存 80%),可能挤占系统预留内存,触发 Linux OOM Killer
- 建议值 = 预估峰值缓存数据体积 × 1.3(留 buffer),且不超过宿主机总内存的 60%
验证方法很简单:INFO memory 查 used_memory_peak_human,观察高峰期后是否稳定回落——如果持续贴近 maxmemory,说明要么该扩容,要么淘汰策略没生效(检查是否真有 key 带 TTL)。
真正麻烦的从来不是选哪个策略,而是确认每一条写入 Redis 的缓存,是否真的按你设想的方式参与淘汰。一次漏设 EX,可能让整个集群的缓存命中率在高峰时段断崖下跌——这种问题不会报错,只会悄悄变慢。


















