首页/数据/Redis 进阶速查/过期机制:惰性删除加定期抽样
内存与管理99 条

过期机制:惰性删除加定期抽样

过期键不会被定时器精确唤醒删除:读取时惰性判定,同时后台周期性随机抽样清理;过期数据占内存的时间取决于抽样强度与写入压力。

Redis 进阶速查数据更新于 2026-10-13

过期机制是怎么工作的

给键设置过期时间只是登记了一个到期时刻,真正的删除由两套机制配合完成:一是惰性删除,任何命令访问到某个键时先检查它是否已过期,过期就删除并按不存在处理;二是定期抽样,服务端在事件循环的空闲时段随机抽取一部分设置了过期时间的键,删除其中已过期的并检查是否执行完毕。两者合起来保证过期键最终会被清理,但删除时刻与到期时刻之间可能存在延迟。

基本信息

两套机制惰性删除(访问时判定)与定期抽样(后台主动清理)
抽样强度active-expire-effort 取值 1 到 10,默认 1,值越大清理越积极
轮询频率hz 默认 10,即每秒 10 次,可调高
内存影响未及时清理的过期键仍占内存,直到被抽样命中
从库行为从库不主动删除,读到逻辑过期的键返回空,实际删除等主库的 DEL 同步

典型使用场景

  • 排查内存与键数不符:键数看起来不多但内存占用高,往往存在大量已过期尚未清理的键
  • 大批键同时到期的治理:给 TTL 加随机抖动,避免同一秒集中过期引发清理压力
  • 读写分离下的正确性:理解从库读到过期键返回空值的行为,避免误判为数据丢失
  • 空闲时段资源紧张时调 hz:需要更及时的过期与内存回收时小步上调,观察 CPU 变化
  • TTL 设置的合理性评估:核心缓存键应都有明确 TTL,只有持久业务键才允许为负一

观察过期状态

观察过期状态
redis-cli CONFIG GET hz                        # 默认 10
redis-cli CONFIG GET active-expire-effort      # 默认 1,越大越积极
redis-cli TTL somekey                          # -1 有键无 TTL,-2 键不存在或已过期
redis-cli INFO keyspace                        # 各库键数与带过期时间的键数
redis-cli DBSIZE                               # 键总数,与 keyspace 交叉核对
redis-cli INFO stats | grep expired_keys       # 累计过期删除计数
redis-cli --scan --pattern 'cache:*' | wc -l   # 抽样统计实际存在的键数量

两种机制对照

机制触发时机覆盖范围
惰性删除命令访问到该键时只清理被访问到的键,保证读取语义正确
定期抽样事件循环的空闲时段每次随机抽一批设有 TTL 的键,逐步收敛
抽样强度active-expire-effort 控制单轮投入强度越高,单轮清理越彻底
轮询频率hz 控制每秒执行次数频率越高,单位时间内的清理机会越多
过期键不是按时删除的:即便到期时刻已过,只要没有任何命令访问它、也没被抽样命中,它就会继续占用内存。因此「内存里键数一直不降」在写入量大的实例上并不罕见,判断时应结合 expired_keys 计数与内存趋势,而不是只看键数。
大量键在同一秒集中过期会给主线程带来阵发性负担:抽样清理、内存回收、以及紧随其后的重建请求会同时发生。设置 TTL 时统一加一段随机抖动是最有效的预防手段,成本却几乎为零。

易错点

  • 缓存键统一设置相同的 TTL,成批同时到期造成集中清理与集中回源,内存与请求压力同时出现尖峰
  • 调高 hz 或抽样强度却不观察 CPU:清理更积极意味着更多轮询开销,空闲余量不足时反而影响正常请求
  • 在从库上观察到过期键返回空值就判断数据丢失,这是复制机制的正常表现,实际删除由主库驱动
  • 认为内存占用由键数量直接决定,忽略未清理的过期键仍占内存,容量评估因此偏乐观

数据来源与参考

  • Redis 官方文档:过期策略说明
  • redis.conf:hz 与 active-expire-effort 注释
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌