如何高效利用Redis的定期与惰性删除机制快速清除过期Key?
- 内容介绍
- 文章标签
- 相关推荐
本文共计848个文字,预计阅读时间需要4分钟。
由于立即删除在工程上不可行——并不是做不到,而是代价太高。如果每个key都配置一个定时器(例如调用setTimer),当有百万级key同时设置了EXPIRE,Redis主线程会被大量定时器回调压榨;修改过期时间还需要重置定时器,进一步加剧压力。延迟队列方案也类似:
GET 或 EXISTS 时触发的惰性删除怎么工作
这是最轻量的“补刀”动作:每次执行读命令前,Redis 会检查目标 key 是否在 db->expires 字典中登记了过期时间,且当前时间已超过该时间戳。一旦确认过期,就当场调用 dbDelete() 删除它,并返回 (nil)。
- 只影响本次访问的那一个
key,不扫描其他数据 - 从不主动触发,所以冷数据(比如长期不用的验证码)可能永远留在内存里
- 主从复制下,从节点不会自己惰性删除——它依赖主节点发来的
DEL命令同步删除
定期删除任务 activeExpireCycle() 怎么控制开销
这个函数藏在 serverCron() 里,默认每秒跑 10 次(由配置项 hz 控制)。它不遍历全部 key,而是:
- 每次随机抽检 20 个设置了过期时间的
key(来自db->expires) - 如果其中过期比例 ≥ 25%,就立即再抽一轮,最多连续执行 25 次(避免单次耗时过长)
- 遍历完当前
db后,下次从下一个db继续,保证压力分散 - 整个过程有硬性耗时限制(默认不超过 1ms),超时即退出
这意味着:哪怕你把 hz 调到 100,它也不会“扫光”所有过期 key,只是提高抽检频率——本质是用可控的 CPU 换内存水位稳定。
真正“快速”清理大量过期 Key 的实操建议
别指望靠默认机制“快速”清空——惰性太懒,定期又太克制。生产环境遇到大批量过期积压(比如缓存预热后集中失效),得人工干预:
- 用
SCAN配合TTL批量识别:先SCAN 0 MATCH * COUNT 1000,再对每个结果跑TTL判断,脚本批量DEL - 临时调高
hz(比如到 50),但必须监控 CPU 使用率,尤其在流量高峰前回退 - 改用
volatile-ttl淘汰策略 +maxmemory限容,让内存快满时优先踢掉快过期的key - 避免让过期时间集中在整点(如全部设成
EX 3600),改用随机偏移:EX 3600 + random(300)
最常被忽略的一点:定期删除只作用于设置了过期时间的 key,而 DEL、FLUSHDB 这类命令才是真正的“立刻删除”,但它们不区分是否过期——该删的删,不该删的也删了。
本文共计848个文字,预计阅读时间需要4分钟。
由于立即删除在工程上不可行——并不是做不到,而是代价太高。如果每个key都配置一个定时器(例如调用setTimer),当有百万级key同时设置了EXPIRE,Redis主线程会被大量定时器回调压榨;修改过期时间还需要重置定时器,进一步加剧压力。延迟队列方案也类似:
GET 或 EXISTS 时触发的惰性删除怎么工作
这是最轻量的“补刀”动作:每次执行读命令前,Redis 会检查目标 key 是否在 db->expires 字典中登记了过期时间,且当前时间已超过该时间戳。一旦确认过期,就当场调用 dbDelete() 删除它,并返回 (nil)。
- 只影响本次访问的那一个
key,不扫描其他数据 - 从不主动触发,所以冷数据(比如长期不用的验证码)可能永远留在内存里
- 主从复制下,从节点不会自己惰性删除——它依赖主节点发来的
DEL命令同步删除
定期删除任务 activeExpireCycle() 怎么控制开销
这个函数藏在 serverCron() 里,默认每秒跑 10 次(由配置项 hz 控制)。它不遍历全部 key,而是:
- 每次随机抽检 20 个设置了过期时间的
key(来自db->expires) - 如果其中过期比例 ≥ 25%,就立即再抽一轮,最多连续执行 25 次(避免单次耗时过长)
- 遍历完当前
db后,下次从下一个db继续,保证压力分散 - 整个过程有硬性耗时限制(默认不超过 1ms),超时即退出
这意味着:哪怕你把 hz 调到 100,它也不会“扫光”所有过期 key,只是提高抽检频率——本质是用可控的 CPU 换内存水位稳定。
真正“快速”清理大量过期 Key 的实操建议
别指望靠默认机制“快速”清空——惰性太懒,定期又太克制。生产环境遇到大批量过期积压(比如缓存预热后集中失效),得人工干预:
- 用
SCAN配合TTL批量识别:先SCAN 0 MATCH * COUNT 1000,再对每个结果跑TTL判断,脚本批量DEL - 临时调高
hz(比如到 50),但必须监控 CPU 使用率,尤其在流量高峰前回退 - 改用
volatile-ttl淘汰策略 +maxmemory限容,让内存快满时优先踢掉快过期的key - 避免让过期时间集中在整点(如全部设成
EX 3600),改用随机偏移:EX 3600 + random(300)
最常被忽略的一点:定期删除只作用于设置了过期时间的 key,而 DEL、FLUSHDB 这类命令才是真正的“立刻删除”,但它们不区分是否过期——该删的删,不该删的也删了。

