volatile与allkeys本质区别在于淘汰范围:前者仅针对设置了TTL的key,后者对所有key一视同仁;volatile策略不触碰永久key,allkeys则可能误删不可重建数据。

volatile 和 allkeys 的区别,本质是「淘汰范围」的划定方式不同:前者只动设置了过期时间(EXPIRE / PEXPIRE / SETEX 等)的 key,后者对所有 key 一视同仁,不管有没有 TTL。
volatile-* 策略只在“临时数据池”里挑人淘汰
Redis 不会把没设过期时间的 key 纳入候选集。比如你用 SET config:timeout 30 存系统参数,它没 TTL,那 volatile-lru 就永远碰不到它——哪怕内存爆了、volatile-lfu 正在狂删其他 key,这个配置项也稳如泰山。
常见误用场景:
- 混存 session(带 TTL)和全局配置(无 TTL)时选了
allkeys-lru,结果配置被随机踢掉,服务开始报错 - 全量数据都没设 TTL,却配了
volatile-ttl,策略直接退化成noeviction,写请求立刻返回OOM command not allowed when used memory > 'maxmemory' - 大量 key 用
EXPIREAT设了相同绝对时间(比如统一过期在凌晨2点),volatile-ttl会因 TTL 值高度趋同而失去排序意义,实际效果接近随机
allkeys-* 策略对所有 key 开放淘汰资格
只要内存超限,allkeys-lru 或 allkeys-lfu 就可能拿走任何 key,包括你用 SET 写入的永久数据。这在纯缓存场景反而是优点:没有“不该删”的 key,缓存重建成本低,命中率更可控。
但代价也很直接:
- 必须确保所有数据都可丢失或可重建,否则就是生产事故
-
allkeys-lfu会给每个 key 维护一个 16 位访问计数器,有额外内存开销;lfu-decay-time设置不合理会导致冷热判断失真 -
maxmemory-samples默认为 5,对allkeys-lfu来说偏低,建议调到 10~20,但 CPU 使用率会上升
选 volatile 还是 allkeys,取决于你的数据有没有“身份标签”
所谓“身份”,就是 TTL —— 它不是可选元数据,而是 Redis 判定 key 是否属于 volatile 淘汰池的唯一依据。如果你的数据天然分两类:一类是“活不过一小时”的缓存(如验证码、临时 token),另一类是“得一直活着”的配置或状态(如开关、白名单),那就该用 volatile-* 系列,靠 TTL 自动划界。
如果你压根不依赖 TTL 做业务逻辑(比如所有 key 都靠应用层控制生命周期),或者所有数据本来就是易失缓存(CDN 元数据、API 响应体),那就别硬加 TTL,直接上 allkeys-* 更干净。
最容易被忽略的一点:volatile 和 allkeys 的区分发生在淘汰决策前一刻,和 key 是怎么写进去的无关。哪怕你用 SETEX 写入,之后又用 PERSIST 移除了过期时间,它就立刻从 volatile 候选池里消失了——Redis 不记“曾经有过 TTL”这种历史。


















