Redis里那些过期的事儿,怎么才能不浪费资源又高效处理
- 问答
- 2026-01-14 04:08:52
- 3
Redis作为一个高性能的内存数据库,它最宝贵的资源就是内存,如果那些设置了过期时间的键(key)在到期之后一直占着内存不释放,那么再大的内存也会被很快耗尽,Redis是怎么处理这些“过期”的事儿,做到既不让它们浪费资源,又能高效运行的呢?这主要依赖于两种核心策略的结合:一种是被动式的惰性删除,另一种是主动式的定期删除,这两种方法就像是一个公司的日常保洁和定期大扫除,互相配合,缺一不可。
被动清理:惰性删除(Lazy Expiration)——用到的时候才检查
惰性删除是Redis处理过期键的第一道防线,也是最直接的一种方式,它的原理非常简单直接:只有当客户端尝试访问一个键的时候,Redis才会顺带检查一下这个键是否已经过期了。
当你对一个键执行GET、HGET等读取命令时,Redis不会立刻给你返回数据,它会先悄悄地去查看这个键的“身份证”——也就是它的过期时间(TTL),如果发现这个键已经过期了(当前时间大于设定的过期时间),那么Redis会立刻做两件事:

- 默默地将这个键从数据库中删除掉,释放它占用的内存。
- 向客户端返回一个空值(nil),就好像这个键从来不存在一样。
这种方式的优点非常明显,就是高效、节省CPU,它把删除操作分散到了每一次具体的键访问上,而且只对那些真正被访问到的过期键进行处理,如果某个键过期后一直没人访问,那么它暂时不会被惰性删除触发清理,这就像是你家里的某个角落,只要你不去动它,就不会特意去打扫它,节省了精力。
惰性删除也有一个致命的缺点:它无法解决“僵尸键”的问题,想象一下,如果一个键过期之后,再也没有任何客户端来访问它,那么它就会像一个幽灵一样,一直占据着宝贵的内存空间,直到永远,这显然是不可接受的,会导致内存泄漏,为了解决这个问题,Redis引入了第二种策略。
主动清理:定期删除(Periodic Expiration)——定时去抽查
为了弥补惰性删除的不足,Redis会定期地、主动地去扫描数据库,找出并删除那些已经过期的键,这个过程是Redis后台自动进行的,不需要客户端的触发,你可以把它理解为公司的定期大扫除,不管平时用不用的角落,到了时间都要检查清理一遍。

Redis的“大扫除”非常聪明,它并不是简单粗暴地每次扫描整个数据库,因为那样会极度消耗CPU资源,导致Redis服务卡顿,无法正常响应客户端的请求,Redis的定期删除策略的核心思想是分而治之,限制执行时长,它的工作流程大致是这样的:
- 定时启动:Redis会每隔一段时间(默认是100毫秒,可通过
hz配置调整)就执行一次定期删除任务。 - 抽样扫描:每次任务启动时,它不会扫描所有数据库的所有键,而是随机抽取一定数量的键(默认是20个,可通过
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP调整)进行检查。 - 删除过期键:对于抽检到的每一个键,检查其是否过期,如果过期就删除。
- 时间控制:最关键的一步是,Redis会严格限制这次扫描任务执行的时间,一旦发现本次操作消耗的CPU时间超过了预设的阈值(比如25毫秒),它就会立刻停下来,即使预设的抽样数量还没检查完也会中止,这样做是为了保证不会因为清理过期键而影响主业务的性能。
这种策略是一个巧妙的权衡,它通过多次、小批量的抽样扫描,逐步地清理掉那些长期未被访问的“僵尸键”,同时通过严格的时间控制,确保了清理动作不会对Redis的响应性能造成明显的影响。
两种策略的配合与内存淘汰机制
在实际运行中,惰性删除和定期删除是协同工作的,惰性删除处理了大部分在过期后很快被访问到的键,而定期删除则负责清理那些“无人问津”的过期键,它们俩一起构成了Redis过期键清理的主体。

即使有这两重保险,在极端情况下仍然可能出现问题,如果短时间内有海量的键同时过期,而定期删除的速度跟不上,或者客户端写入数据的速度远远大于过期键清理的速度,内存还是有可能被占满。
为了应对这种“保险也失灵”的情况,Redis还设置了最后一道防线——内存淘汰机制(Eviction Policies),当Redis的内存使用达到上限时,它会根据用户预先配置的淘汰策略(如allkeys-lru:淘汰最近最少使用的键;volatile-ttl:淘汰过期时间最近的键等),主动删除一些键(可能是过期的,也可能是未过期的)来腾出空间,确保新的数据可以写进来。
总结一下
Redis通过“惰性删除”(用时检查,立即清理)和“定期删除”(定时抽样,渐进清理)这两种主从结合的方式,高效地管理着过期键,前者保证了常规操作的速度,后者解决了内存泄漏的风险,最后再用“内存淘汰机制”作为兜底方案,防止内存被彻底耗尽,这套组合拳使得Redis在绝大多数场景下,都能在保持高性能的同时,智能地回收资源,避免浪费。
(参考资料:Redis官方文档中关于“Expiration”和“LRU cache”的章节,以及相关开发者博客对过期策略的解读。)
本文由太叔访天于2026-01-14发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/80332.html
