Redis到底怎么搞定键过期的,底层机制和技术细节是啥样的?
- 问答
- 2025-12-31 21:44:55
- 1
Redis搞定键过期,主要靠两招组合拳:被动过期(惰性删除) 和 主动过期(定期删除),它不是单一机制,而是多种策略协同工作的结果,目的是在内存占用和CPU消耗之间找到一个平衡点。
第一招:被动过期(Lazy Expiration)—— 用到时才检查

这是最简单直接的方式,当客户端尝试访问一个键时(比如执行 GET key),Redis不会立即去检查这个键是否过期,而是在这个键被“碰”到的时候才进行检查。
- 具体过程:在执行任何读取或写入该键的命令之前,Redis会先偷偷地检查一下这个键的“过期时间”(expire time),如果发现当前时间已经超过了预设的过期时间,那么这个键就会被立即删除,然后Redis会像这个键从来不存在一样返回给客户端(
GET命令返回 nil)。 - 优点:非常省CPU,因为只有在键被访问时才会消耗资源进行检查,如果一堆键永远没人访问,那么即使它们已经过期了,Redis也不会主动去清理它们,从而避免了无谓的计算。
- 缺点:对内存不友好,如果有很多键设置过期后,再也没有被访问过,它们就会一直赖在内存里,成为“僵尸键”,白白占用内存空间,直到有一天被访问才会被清理,显然,只靠这一招是不行的。
第二招:主动过期(定期删除)—— 定时扫一扫

为了解决“僵尸键”的问题,Redis需要一个主动清理的机制,这就是定期删除,它不像闹钟一样准时准点,而是以一种自适应的、分批的方式在后台运行。
- 具体过程:Redis会每隔一段时间(默认是每100毫秒,可配置)就执行一次清理任务,但这个任务不是一口气扫描整个数据库,那样会卡住Redis(因为Redis是单线程的,长时间阻塞会影响所有命令),它的做法很聪明:
- 随机抽样:每次任务,它会从设置了过期时间的键的集合中,随机抽取一定数量的键(比如20个)进行检查。
- 删除已过期键:检查这20个键,删除其中所有已经过期的键。
- 判断清理进度:统计一下这次抽样中过期键的比例,如果比例很高(比如超过25%),说明这个数据库中可能还有很多过期键“潜伏”着,Redis会立刻再来一次抽样和删除,循环这个过程,直到过期键的比例降到一个比较低的水平(比如低于25%),这样就能确保在过期键很多时,清理工作会加速进行;而当过期键不多时,就只做少量检查,避免CPU过度消耗。
- 优点:弥补了被动过期的不足,能够逐步地清理掉那些不被访问的过期键,防止内存无限增长。
- 缺点:由于是抽样和自适应的,它无法保证所有过期键都能在到期后“秒删”,会有一个短暂的时间窗口(通常很短,最多几百毫秒到一秒)内,过期键仍然存在,这对于绝大多数应用来说是可以接受的。
底层数据结构:过期字典(Expires Dictionary)

Redis是怎么知道一个键什么时候过期呢?它内部维护了一个叫做“过期字典”的哈希表(来源:《Redis设计与实现》)。
- 这个字典长啥样:你可以把它想象成一个花名册,这个花名册的“键”就是数据库里那些设置了过期时间的键的指针(指向实际的键对象),而“值”就是一个long long类型的整数,记录了这个键的过期时间戳(以毫秒为单位的UNIX时间戳)。
- 怎么用:当设置
EXPIRE key 30时,Redis就在这个过期字典里添加一条记录:键是key,值是(当前时间戳 + 30秒),当需要检查键是否过期时,无论是被动检查还是主动检查,都是去这个字典里查一下,拿当前时间戳和字典里记录的时间戳比较一下就行了。
其他相关细节
- AOF和RDB持久化时的处理:
- 生成RDB快照时:Redis在创建RDB文件时,会检查键的过期时间,只有那些未过期的键才会被保存到RDB文件中,过期键就像不存在一样,不会被持久化。
- AOF日志重写时:和RDB类似,在执行BGREWRITEAOF重写AOF文件时,Redis也是先检查键是否过期,只将未过期的键的写命令写入新的AOF文件。
- AOF日常追加时:当一个键因为过期被删除后(无论是被动还是主动删除),Redis会向AOF文件追加一条
DEL key命令,这样从AOF恢复数据时,这个过期键也会被正确地清除。
- 主从复制下的行为:在主从架构中,为了保持数据的一致性,过期键的删除操作是由主节点主导的,主节点在删除一个过期键后,会向所有从节点发送一个
DEL命令,从节点即使自己发现某个键过期了(比如通过自己的定期删除逻辑),也不会擅自删除它,而是等待主节点的DEL命令,这保证了数据删除的唯一决策权在主节点,避免了混乱。
总结一下
Redis的过期机制是一个巧妙的混合系统:
- 核心是“过期字典”,它记录了每个该过期的键和它的死期。
- 日常靠“被动过期”,谁来访问就检查谁,节省CPU。
- 辅助以“主动过期”,定期随机抽样清理,防止内存泄漏。
- 在持久化和主从复制时,有相应的策略保证数据最终的一致性。
这种设计使得Redis能够以很小的性能代价,高效地管理海量键的过期问题,既保证了响应速度,又控制了内存的使用。
本文由畅苗于2025-12-31发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/72076.html
