volatile-ttl 并非优先删除快过期key,仅在内存达限、有写入操作、且存在ttl>0的key三者同时满足时,随机采样20个带ttl的key并淘汰其中ttl最小者,不全量扫描、不主动清理、不保证命中濒死key。

volatile-ttl 不是“快过期就优先删”,它只在内存真正触顶 + 有写入时,从已设 TTL 的 key 中随机抽样一批,挑出里面 ttl 返回值最小的那个删掉——不是全量扫描,不保证精准,也不主动清理。
volatile-ttl 的触发条件比文档写的更苛刻
它不会因为某个 key 剩 1 秒就提前盯上它。真实生效必须同时满足:
-
maxmemory已配置且当前内存使用 ≥ 该阈值 - 发生写入操作(如
SET、LPUSH、HSET),触发freeMemoryIfNeeded()流程 - 数据库中存在至少一个
ttl key返回正整数的 key(即未过期、已设 TTL)
这三个条件缺一不可。没写入?不删。内存还剩 1MB?不删。所有 key 的 ttl 都返回 -1(没设过期)或 -2(已逻辑过期)?那这次淘汰直接跳过,等下一次写入再试。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
为什么你查不到“马上过期”的 key 被删了
因为 volatile-ttl 的采样是随机的,默认只看 20 个 key。哪怕你有 10 万个带 TTL 的 key,其中 99999 个还剩 1 小时,1 个只剩 1 秒——只要这 1 个没被抽中,它就安全到下次写入。
-
ttl key返回-2的 key(已逻辑过期但未物理删除)会被忽略,不参与候选 -
PERSIST过的 key 或刚EXPIRE但状态未刷新的 key,可能因ttl暂时读不出正整数而漏掉 - Redis 的
expires字典本身无序、不索引,不存在“按 TTL 排序遍历”这回事
想让快过期 key 更大概率被清掉,只能绕开 volatile-ttl 本身
靠调参数或换策略,而不是指望它变聪明:
- 把
hz从默认 10 提到 50–100:让activeExpireCycle()更频繁执行定期删除,提高过期 key 被抽中并清理的概率(代价是 CPU 占用上升) - 业务层统一用
EXPIREAT或PEXPIREAT设绝对过期时间点,再起定时任务跑KEYS pattern+TTL扫描,主动DEL剩余 TTL 极低的 key(生产慎用KEYS,可用SCAN替代) - 改用
volatile-lfu:以访问热度为主维度,TTL 仅作过滤条件,至少能避免长期不访问又快过期的 key 占着内存不走
真正容易被忽略的是:volatile-ttl 的“ttl”值来自 redisDb.expires 字典里存的绝对时间戳减去当前时间,而这个字典不维护任何顺序或索引。所有对“精准淘汰濒死 key”的预期,本质上都建立在对底层数据结构的误判上。










