一、Redis 的过期策略是什么
Redis 并没有采用「每个 key 到期就立刻删除」的方案,因为那样需要为每个 key 维护定时器,开销太大。它实际用的是两种策略配合:
1. 惰性删除(Lazy Deletion)
-
当客户端访问某个 key 时,Redis 才会检查它是否过期。
-
如果已过期,就删除并返回空。
-
优点:对 CPU 友好,只在访问时才做检查。
-
缺点:如果某个过期 key 一直不被访问,它会一直占着内存,造成内存泄漏。
2. 定期删除(Active/Periodic Deletion)
-
Redis 会周期性地主动扫描一部分设置了过期时间的 key,删除其中已过期的。
-
这是对惰性删除的补充,防止过期 key 长期占用内存。
惰性删除保证访问时不会拿到过期数据,定期删除负责兜底清理,两者结合。
二、底层实现:过期字典 + 定期删除的具体逻辑
过期字典(expires dict)
-
Redis 每个数据库(redisDb)里有一个
expires字典,专门存放「设置了过期时间的 key」和它的到期时间戳。 -
注意:只有设置了 TTL 的 key 才会进这个字典,没设过期时间的 key 不在这里。
定期删除的执行细节
Redis 默认每秒执行 10 次(hz 配置,默认 10)过期扫描,每次的逻辑大致是:
-
从过期字典中随机抽取 20 个 key;
-
删除其中已过期的 key;
-
如果这 20 个里有超过 10%是过期的,说明过期 key 比例还很高,就再抽 20 个继续删;(“这个阈值取决于 Redis 版本。在较老的版本里是 25%,而 Redis 7.0 之后,默认调低到了 10%,意味着清理行为会变得更积极一些。”)
-
重复直到过期比例低于 10%,或者本轮扫描时间超过 25ms(防止阻塞主线程)。
其中有几个重要参数:
1、定期删除的频率(hz参数):z 默认为 10,代表每秒执行 10 次,也就是每秒钟进行 10 次尝试来查找并删除过期的 key。 hz 的取值范围为 1~500。增大 hz 参数的值会提升定期删除的频率。如果你想要更频繁地执行定期删除任务,可以适当增加 hz 的值,但这会增加 CPU 的使用率。根据 Redis 官方建议,hz 的值不建议超过 100,对于大部分用户使用默认的 10 就足够了。
2、每次随机抽查的数量: Redis 7.2 版本为 20,也就是说每次会随机选择 20 个设置了过期时间的 key 判断是否过期。
3、执行时间阈值:执行时间已经超过了阈值,那么就中断这一次定期删除循环,以避免使用过多的 CPU 时间。
4、过期 key 比例:如果这一批过期的 key 比例超过一个比例,就会重复执行此删除流程,以更积极地清理过期 key。相应地,如果过期的 key 比例低于这个比例,就会中断这一次定期删除循环,避免做过多的工作而获得很少的内存回收。
这里的关键点:
-
随机抽样而不是全量扫描,是为了控制 CPU 占用;
-
10% 阈值 + 时间上限,是为了在「清理干净」和「不阻塞」之间做平衡;
-
Redis 是单线程处理命令的,所以定期删除必须严格限时,否则会卡住正常请求。

1343

被折叠的 条评论
为什么被折叠?



