Redis 的 Key 过期删除策略,可以说是其内存管理中最有趣、也最常被问到的部分。它并不是靠单一机制来清理过期数据,而是有一套组合拳:被动删除和主动删除双管齐下。这套设计到底是怎么运作的?我们一步步拆开看。 1. 被动删除(惰性删除 - Lazy Expiration) 工作原理 说白了就是:你
Redis键过期删除策略使用小结
时间:2026-07-07
浏览:174
文章目录
Redis 的 Key 过期删除策略,可以说是其内存管理中最有趣、也最常被问到的部分。它并不是靠单一机制来清理过期数据,而是有一套组合拳:被动删除和主动删除双管齐下。这套设计到底是怎么运作的?我们一步步拆开看。
1. 被动删除(惰性删除 - Lazy Expiration)
工作原理
说白了就是:你不找我,我就不删。当客户端发起请求、访问某个 Key 时,Redis 会先检查一下这个 Key 是否已经过期。如果过期了,当场删除,然后返回 nil——就像它从来没存在过一样。如果还活着,那就正常返回数据。
优点
对 CPU 极其友好。只有在被访问的那一刻才消耗资源,其他时间完全不动。简单直接,不影响那些无人问津的 Key。
缺点
对内存不太友好。如果某些过期 Key 永远没人访问,它们就会一直赖在内存里不走。极端情况下,可能造成内存浪费甚至是“泄露”。
2. 主动删除(定期删除 - Periodic Expiration)
工作原理
既然光靠被动删除不靠谱,Redis 还会主动出击。它以一个固定的频率(默认每秒 10 次)执行以下步骤:
- 随机抽检:从设置了过期时间的 Key 集合中,随机挑出 20 个。
- 过期清理:把这 20 个里面已经过期的 Key 删除掉。
- 动态循环:如果这次抽检中,超过 25% 的 Key 都过期了,那就说明过期 Key 积压严重,需要继续重复步骤 1 和 2。
- 时间阀值:为了防止影响主线程,每次扫描最多只持续 25ms。时间一到,不管清没清完,立刻收工。
对应的配置参数(在 redis.conf 中):
# 每秒执行过期扫描的次数(默认 10)
hz 10
# 每次扫描的 CPU 时间百分比上限(默认 25%)
# 实际上每次扫描最多 25ms(1000ms / hz * 25%)
优点
能在内存中减少过期 Key 的堆积,在 CPU 消耗和内存占用之间找到一个不错的平衡点。
缺点
不是实时的,可能存在某个 Key 已经过期几分钟了,但还没被扫描到的情况。而且,定期执行本身也增加了一定的 CPU 开销。
3. 内存淘汰策略(Eviction Policies)
如果说前两种策略是“日常保洁”,那当内存真的撑不住了——也就是达到了 maxmemory 限制时——Redis 就会启动最后防线:根据你配置的淘汰策略来强行腾空间。
# 内存限制(默认不限制)
maxmemory
# 淘汰策略
maxmemory-policy
可选的淘汰策略有这么几种:
| 策略 | 描述 | 适用场景 |
|---|---|---|
| noeviction | 不淘汰,直接返回错误 | 数据绝对不能丢失 |
| allkeys-lru | 从所有 Key 中选出最近最少使用的淘汰 | 需要缓存效果 |
| volatile-lru | 从设置了过期时间的 Key 中选出最近最少使用的淘汰 | 混合使用 |
| allkeys-random | 从所有 Key 中随机淘汰 | 所有 Key 同等重要 |
| volatile-random | 从设置了过期时间的 Key 中随机淘汰 | 混合使用 |
| volatile-ttl | 淘汰即将过期的 Key(TTL 最小的) | 优先保留新数据 |
| allkeys-lfu | 从所有 Key 中选出最不经常使用的淘汰(4.0+ 版本) | 访问频率更重要 |
| volatile-lfu | 从设置了过期时间的 Key 中选出最不经常使用的淘汰(4.0+ 版本) | 混合使用 |
4. 实际工作流程示例

5. 性能优化建议
监控过期 Key 数量
想知道系统中有多少 Key 已被清理?可以这样查:
redis-cli info stats | grep expired_keys
合理配置 hz 值
hz 值决定了主动扫描的频率。
hz 100 # 更高频率,清理更及时,但 CPU 消耗也更高
hz 1 # 更低频率,CPU 友好,但可能导致过期 Key 堆积
避免大量 Key 同时过期
这是一个非常经典的优化点。如果大批 Key 在同一秒过期,会导致 Redis 在那一瞬间的 CPU 飙升。通常的做法是加入随机偏移量:
# 不好的做法:同时设置相同过期时间
for i in range(100000):
redis.set(f"key:{i}", "data", ex=3600)
# 好的做法:添加随机偏移
for i in range(100000):
redis.set(f"key:{i}", "data", ex=3600 + random.randint(0, 300))
6. 特殊情况处理
AOF/RDB 持久化
- RDB:生成快照时,过期的 Key 不会被保存到文件中。
- AOF:当 Key 过期时,Redis 会追加一条 DEL 命令到 AOF 文件里。
主从复制
- 主节点删除过期 Key 后,会主动向从节点发送一条 DEL 命令。
- 从节点没有自主删除过期 Key 的权限,完全听命于主节点的指令。
集群模式
- 每个节点独立管理自己的过期 Key。
- 当槽位发生迁移时,Key 的过期信息也会一并迁移到目标节点。
总结
Redis 的过期删除策略,本质上就是一套 惰性删除 + 定期删除 的组合拳:
- 惰性删除:保证每次访问的“正确性”,确保不会返回已过期的数据。
- 定期删除:作为补充,主动清理那些无人访问的过期 Key,减少内存浪费。
- 内存淘汰:在极端情况下,作为防止内存耗尽的最后一道防线。
这套机制在 CPU 使用率、内存效率和实现复杂性之间,取得了相当不错的平衡。也正是因此,Redis 才能在高并发场景下流畅地处理海量带有过期时间的 Key。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。