← 返回首页

Redis 怎么淘汰过期 key?

Redis 过期 Key 淘汰机制(分两套:过期删除 + 内存满时淘汰)

一、过期 Key 删除策略(针对设置了 TTL 的键)

Redis 处理过期 key 有三种策略同时配合,不存在单一方案。

1. 惰性删除(被动删除,访问时才删)

  • 逻辑:只有当客户端读取 key 时,Redis 先检查是否过期,过期直接删除并返回 nil
  • 优点:不占用 CPU,平时无额外开销。
  • 缺点:如果 key 长期不被访问,哪怕早已过期,会一直占用内存。

2. 定期主动删除(后台定时扫描)

Redis 后台每隔一段时间执行定时任务,随机抽取一批带过期的 key 检测清理:
  1. 每秒执行 10 次(hz=10,可配置);
  2. 每次随机抽取20 个带过期的 key;
  3. 删除其中所有已过期 key;
  4. 若本轮删除的过期 key 超过 25%,立刻重复本轮扫描,防止大量过期堆积。
  • 优点:主动释放内存,弥补惰性删除缺陷。
  • 缺点:不会全库遍历,冷门长期未访问的过期 key 仍可能残留。

3. 内存淘汰(maxmemory 触发,最关键兜底)

当内存达到 maxmemory 上限时,Redis 执行淘汰策略,这里会同时清理:
  1. 优先删掉所有已过期的 key;
  2. 若清理完过期 key 内存仍不足,再根据配置策略删除未过期的正常 key。

二、6 种内存淘汰策略(maxmemory-policy

maxmemory 10gb maxmemory-policy volatile-lru
分为两大类:只淘汰带过期的 key淘汰全部 key

只针对设置了 TTL 的 key(volatile 系列)

  1. volatile-lru(常用默认) 从有过期时间的 key 中,淘汰最近最少使用的。
  2. volatile-lfu 淘汰访问频率最低的 key(Redis4.0+)。
  3. volatile-random 随机删除带过期的 key。
  4. volatile-ttl 优先删除剩余存活时间最短的 key。

所有 key 都参与淘汰(allkeys 系列)

  1. allkeys-lru 全部 key 里删最少使用,适合缓存场景。
  2. allkeys-lfu 全部 key 删访问频率最低。

拒绝淘汰(生产极少用)

  • noeviction:内存满直接报错,不删任何 key,写入返回 OOM。

三、完整过期清理流程(时序)

  1. 写入 key 带 expire:存入过期字典(expires) 记录到期时间;
  2. 日常:
    1. 客户端读 key → 惰性删除;
    2. 后台定时任务 → 随机批量清理过期;
  3. 内存达到 maxmemory: ① 先遍历清理所有过期 key; ② 内存仍超阈值,按 maxmemory-policy 删正常 key;
  4. RDB/AOF 持久化:
    1. RDB:持久化时忽略已过期 key;
    2. AOF:key 过期删除时生成 DEL 指令写入 AOF。

四、补充关键细节

  1. 过期精度:毫秒级,基于系统时间;修改服务器时间会导致过期判断错乱。
  2. 主从过期同步: 主库删除过期 key 后,会向从库发送 DEL 命令;从库不会主动执行过期删除,只同步主库删除结果,避免主从不一致。
  3. 批量清理过期命令:
    1. SCAN 遍历过滤过期;
    2. UNLINK 异步删除大 key,不阻塞主线程;
    3. EXPIRE / PEXPIRE 设置过期。
  4. 优化建议:
    1. 缓存场景推荐 allkeys-lru
    2. 部分持久数据 + 缓存混合用 volatile-lru
    3. 大 key 尽量用 UNLINK 替代 DEL
    4. 合理设置 maxmemory,不要等系统 OOM。

极简总结

日常靠「惰性删除 + 定期扫描」清过期;内存撑爆时先清全部过期,不够再按 LRU/LFU 等策略删正常 key。