volatile-ttl策略通过随机采样带过期时间的key,从中淘汰ttl最小者,实现低优先级key更早被淘汰;它不扫描全量、仅依赖ttl差异,且未设过期时间的key不参与淘汰。

Redis 本身不支持按业务维度设置「Key 优先级」,也没有内置的权重机制。但你可以利用 volatile-ttl 淘汰策略 + 合理控制不同 Key 的 TTL 值,间接实现「高优先级 Key 存活得更久、低优先级 Key 更早被淘汰」的效果。
volatile-ttl 策略如何依赖 TTL 值做淘汰决策
当 Redis 内存达到 maxmemory 且启用 volatile-ttl 时,它会在所有设置了过期时间的 Key 中,**随机采样一批(默认 5 个),从中选出 TTL 最小的那个淘汰**。注意:不是全局扫描所有过期 Key,而是采样后局部比较 —— 所以 TTL 差异要足够明显,才能提高「低优先级 Key 先被选中」的概率。
关键点:
-
TTL值越小,该 Key 在采样中被选为淘汰目标的概率越高 - 没设置过期时间的 Key 不会进入候选池,
volatile-ttl对它们完全无效 - 如果当前所有带过期时间的 Key 的
TTL都大于 300 秒,而你期望某类缓存 60 秒就让出内存,那必须显式设EXPIRE key 60
如何为不同业务 Key 分配有区分度的 TTL
不能只靠「业务重要性」拍脑袋定 TTL,得结合访问模式和容忍延迟反推:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 高频读写、强一致性要求的业务(如用户登录态):设较长 TTL(如
3600),并搭配volatile-lru或allkeys-lru防止突发写入挤掉它 - 临时计算结果、降级兜底数据(如推荐 fallback 缓存):设极短 TTL(如
60或30),确保内存紧张时优先被清掉 - 静态配置类(如开关、白名单):可设超长 TTL(
86400),甚至不设过期 —— 但要注意:不设过期的 Key 在volatile-*策略下完全免疫淘汰 - 避免 TTL 过于接近:比如 A 类设
300、B 类设301,实际淘汰倾向几乎无差别;建议至少拉开 3~5 倍差距(如120vs600)
为什么不能只靠 volatile-ttl 实现精准优先级
Redis 的 TTL 淘汰是概率性、采样式的,不是精确排序。这意味着:
- 即使某个 Key 的
TTL是全场最小,它也不保证「下一次淘汰一定轮到它」 - 若业务 Key 总数极少(比如只有 3 个带过期的 Key),采样可能反复命中同一组,导致淘汰不均衡
-
PTTL命令返回值:key 不存在时是-2,未设过期是-1,这些边界值在监控脚本里容易误判为「即将淘汰」 - 如果误将核心 Key 设了短 TTL,又启用了
volatile-ttl,它反而比其他 Key 更危险 —— 这种错误在线上很常见
真正可控的替代方案:用命名空间 + allkeys-lru 配合业务逻辑
如果你发现靠 TTL 差值调控太不可靠,更稳的做法是放弃 volatile-* 系列,改用 allkeys-lru,然后在业务层控制访问频次:
- 给高优先级 Key(如用户 session)定期执行
GET或TOUCH,保持其 LRU 时间戳最新 - 低优先级 Key(如日志聚合中间结果)写入后从不主动读,自然成为 LRU 尾部候选
- 用统一前缀隔离业务域(如
sess:u1001、tmp:report_20260528),便于后续通过SCAN+TTL批量分析淘汰倾向 - 注意:
TOUCH在 Redis 6.0+ 才支持,老版本只能靠GET+ 忽略返回值
真正决定淘汰顺序的,从来不是你写的那个数字,而是 Redis 实际采样时看到的 TTL 分布和你的 Key 访问节奏。把 TTL 当作信号而非开关,才能避开「设了 60 秒却总不被淘汰」或「设了 3600 秒结果第一天就被扫光」这类典型陷阱。










