Redis淘汰策略需显式配置maxmemory才生效,否则无论策略如何设置均不触发;其与持久化机制相互独立,但配置不当会导致缓存失效或策略失效。

不冲突,但配置不当会让持久化失效或淘汰策略“形同虚设”。
Redis 的淘汰策略和持久化是两套独立机制:淘汰策略管「内存不够时删谁」,持久化管「断电后数据怎么留」。它们各自触发条件不同、作用对象不同、甚至底层数据结构都不同。真正出问题的,往往是配置顺序、参数组合或对行为的误解。
maxmemory 必须显式设置,否则淘汰策略不生效
很多人以为只要配了 maxmemory-policy allkeys-lru,Redis 就会自动开始淘汰——其实不会。maxmemory 默认是 0(不限制),此时无论策略选什么,Redis 都会一直往内存里塞,直到系统 OOM。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 必须在
redis.conf中明确设置maxmemory,单位是字节,比如maxmemory 2gb或maxmemory 2147483648 - 推荐值:物理内存的 60%~75%,预留空间给 OS、fork 进程、AOF rewrite 等
- 验证是否生效:
CONFIG GET maxmemory返回非零值;INFO memory中used_memory接近maxmemory时观察淘汰是否发生 - 常见坑:用
CONFIG SET maxmemory临时修改后没写入 conf 文件,重启即丢失
RDB/AOF 不保存被淘汰的 key,但会影响淘汰判断时机
淘汰只发生在内存中,而 RDB 和 AOF 只记录「当时还活着的 key」。所以被 volatile-lru 淘汰掉的 key,不会出现在 dump.rdb 或 appendonly.aof 里——这本身不是 bug,而是设计如此。
- 但注意:AOF rewrite 或 RDB save 过程中,Redis 会 fork 子进程。此时主进程仍在接收写请求,如果新写入导致内存超限,淘汰会照常发生;但 fork 出的子进程看到的是 fork 时刻的内存快照,它不知道哪些 key 刚被淘汰,所以生成的 RDB/AOF 文件可能比当前内存状态“多”一些 key(即淘汰前刚写入、还没来得及淘汰的)
- 更隐蔽的问题:如果 AOF 开启且
appendfsync always,每次写都刷盘,磁盘 I/O 延迟高 → 写请求堆积 → 内存增长更快 → 更早触发淘汰 → 实际缓存命中率下降 - 建议搭配:淘汰策略用
allkeys-lru或volatile-lru,AOF 用appendfsync everysec,RDB 关闭或拉长间隔(如save 3600 1)
volatile-* 类策略依赖 expire 设置,漏设 = 策略失效
volatile-lru、volatile-ttl 这类策略只看「有没有过期时间」,不看「是不是缓存数据」。如果你忘了对 key 执行 EXPIRE 或 SETEX,哪怕业务上它是临时数据,Redis 也当它是永久数据,完全不参与淘汰。
- 检查方法:
SCAN 0 MATCH *+TTL key,看有多少 key 返回-1(永不过期)或-2(已过期但未清理) - 修复手段:批量补过期时间(慎用!避免阻塞),或改用
allkeys-lru;长期方案是业务层强制所有缓存写入走SETEX/SET key value EX 3600 - 陷阱:
INCR、HINCRBY等命令不会继承原 key 的 TTL,需手动EXPIRE - LFU 模式下,
volatile-lfu对访问频次敏感,但前提是 key 有EXPIRE,否则压根不进候选池
淘汰 + 持久化共存时,最易被忽略的其实是监控盲区
你配好了 maxmemory、maxmemory-policy、appendonly yes,一切看似正常,但 INFO stats 里的 evicted_keys 持续上涨,INFO persistence 显示 rdb_last_bgsave_status:ok,就真没问题?不一定。
- 关键指标要联动看:
used_memory_peak是否远高于maxmemory(说明淘汰滞后);expired_keys和evicted_keys比值是否异常(比如前者为 0,后者飙升,说明大量 key 没设过期) -
latest_fork_usec超过 100ms,意味着每次 RDB/AOF rewrite 都可能引发主线程卡顿,间接加剧内存压力 - 真正危险的是「淘汰发生但客户端无感知」:比如
noeviction下写失败会直接报(error) OOM command not allowed when used memory > 'maxmemory'.,而allkeys-lru下写成功但旧 key 被删,业务若没做兜底(如查 DB),就会返回空结果

















