Redis 超过 maxmemory 后如何处理,取决于 maxmemory-policy。内存满了不等于所有写入都自动失败,也不等于一定删除最旧的 Key。 下表列出 Redis 7.x 常见的八种经典策略;新版本新增的策略应查看对应版本配置。
策略怎么选?
| 策略 | 候选范围与选择方式 |
|---|---|
| noeviction | 不淘汰,需要增加内存的写命令可能报错 |
| allkeys-lru | 所有 Key 中近似淘汰最近最少使用的 |
| allkeys-lfu | 所有 Key 中近似淘汰使用频率较低的 |
| allkeys-random | 所有 Key 中随机选 |
| volatile-lru | 只在带 TTL 的 Key 中按近似 LRU 选择 |
| volatile-lfu | 只在带 TTL 的 Key 中按近似 LFU 选择 |
| volatile-random | 只在带 TTL 的 Key 中随机选 |
| volatile-ttl | 优先淘汰剩余 TTL 较短的候选 Key |
纯缓存实例通常允许丢缓存并回源,可考虑 allkeys-lru 或 allkeys-lfu,再根据访问分布和命中率评估。既存缓存又存不能随意丢失的数据时,volatile 策略只有在正确规划 TTL 的前提下才有意义;更清晰的做法往往是按业务职责隔离实例。没有合格的带 TTL 候选 Key 时,volatile 策略也可能无法释放内存并返回错误。
maxmemory 为什么不能直接等于机器内存?
Redis 进程的 RSS、操作系统和其他进程的内存、复制/AOF 缓冲、后台 fork 的写时复制峰值,都需要余量。用于触发淘汰的统计也不简单等于 RSS;部分复制和 AOF 缓冲内存不纳入相同的淘汰计算,避免淘汰产生复制数据进而不断放大缓冲。
排查时一起看 INFO memory、INFO stats 中的使用量、内存上限、evicted_keys 和命中情况。淘汰次数增长但命中率稳定,可能是正常缓存行为;命中率下降并带来数据库压力,则应检查容量、TTL、BigKey 与业务流量。
常见追问
noeviction 下 GET 也失败吗?
并非所有命令失败。读取一般仍可工作,释放内存的操作也有用;主要风险是需要增加内存的写入被拒绝,应用必须处理错误。
设置 TTL 就能保证内存不会满吗?
不能。写入速度可能高于过期回收速度,过期时间也可能过长;同时要设置容量上限并规划淘汰或业务限额。
锁和计数器能跟普通缓存共用淘汰实例吗?
需要谨慎。锁被提前淘汰可能破坏互斥,计数器丢失可能影响限流。应隔离关键协调数据,且不能把 Redis 当成唯一业务正确性保障。
为什么淘汰了很多 Key,RSS 没有立刻下降?
内存分配器可能保留空闲页,碎片和后台任务也会影响 RSS。要区分逻辑数据减少与操作系统看到的驻留内存减少。