Redis里怎么给数据加有效期,存储过期信息的那些事儿
- 问答
- 2026-01-14 22:55:38
- 4
在Redis中,给数据设置有效期是一个非常常用且核心的功能,它让我们可以轻松管理数据的生命周期,比如实现缓存、验证码过期、限时活动等场景,这事儿说起来简单,但背后Redis是怎么处理和存储这些过期信息的,却有不少门道。
如何给数据设置有效期?
根据Redis官方文档和普遍的使用方法,主要有以下几种方式给数据加“保质期”:
-
在设置键值对的同时指定过期时间
SET key value EX seconds:这是最常用的命令。SET login:token "user123" EX 300,意思是将键login:token的值设置为 “user123”,并且它在300秒(5分钟)后会自动过期,这里的EX单位是秒。SET key value PX milliseconds:这个命令和上面的类似,但过期时间是以毫秒为单位指定的,精度更高。SET captcha:1234 "ABCD" PX 60000表示验证码在60秒后过期。SET key value EXAT timestamp:这个命令允许你指定一个精确的Unix时间戳(秒级),表示键将在哪个具体的时间点过期。SET event:start "begin" EXAT 1672502400表示该键在2023年1月1日00:00:00 UTC过期。SET key value PXAT timestamp:和EXAT类似,但指定的是毫秒级的时间戳。
-
对已存在的键单独设置过期时间 有时候我们可能先创建了一个键,后来才需要给它加上过期时间,这时可以用以下命令:

EXPIRE key seconds:为已存在的键key设置在seconds秒后过期。PEXPIRE key milliseconds:以毫秒为单位设置过期时间。EXPIREAT key timestamp:为键设置一个过期的绝对时间点(秒级时间戳)。PEXPIREAT key timestamp:为键设置一个过期的绝对时间点(毫秒级时间戳)。
-
查看和移除过期时间
TTL key:查看键剩余的存活时间,单位是秒,如果返回-2,表示键不存在;返回-1,表示键存在但没有设置过期时间。PTTL key:和TTL类似,但返回的是毫秒。PERSIST key:如果一个键设置了过期时间,使用这个命令可以移除它的过期时间,使其成为一个永久的键。
Redis是怎么存储和管理这些过期信息的?(存储过期信息的那些事儿)
这部分是重点,也是大家常说的“背后的故事”,Redis并不是为每个键值对额外存储一个“过期时间”字段那么简单,它采用了两种主要的策略来高效地管理海量键的过期,这两种策略是结合使用的。

-
过期字典(Expires Dictionary) 根据对Redis源码的分析(如知乎用户“程序员小灰”等人的解读),Redis内部维护了一个叫做“过期字典”的特殊数据结构,你可以把它想象成一个哈希表,这个字典的“键”指向Redis数据库中那些设置了过期时间的键,而字典的“值”则保存了该键的过期时间点(一个毫秒精度的Unix时间戳)。 当我们使用
EXPIRE、PEXPIREAT等命令时,Redis实际上就是在向这个过期字典里插入或更新一条记录,当需要检查一个键是否过期时,Redis会先到这个字典里查一下,如果找不到记录,说明这个键是永久的;如果找到了,就把当前时间戳和字典里存储的过期时间戳进行比较,判断是否过期。 -
过期键的删除策略 光知道哪个键什么时候过期还不够,关键是要在它过期后把它清理掉,释放内存,Redis采用了两种删除策略的结合:
- 惰性删除(Lazy Expiration):这种策略很简单,用到的时候才检查”,当客户端尝试访问一个键时,Redis会先去检查它的过期时间(查询上述的过期字典),如果发现键已经过期,就立刻删除它,然后返回空值,就像这个键不存在一样,这种策略的优点是节省CPU,因为只在实际访问时才会付出检查的代价,缺点是如果过期键永远不被访问,那么即使它已经过期,也会一直占用着内存,造成内存泄漏。
- 定期删除(Periodic Expiration):为了解决惰性删除可能造成的内存泄漏问题,Redis会定期地主动检查和删除一批过期键,这个过程不是扫描整个数据库,而是抽样进行,Redis会每隔一段时间(默认配置是每秒10次,即100ms一次)随机从设置了过期时间的键中抽取一小部分(比如20个键),检查它们是否过期,如果过期的比例很高,说明当前数据库中有很多键已经过期,Redis会再次抽取更多的样本进行检查和删除,直到过期的比例降下来,这种策略是惰性删除的一个补充,在CPU和内存之间取得了一个平衡。
一些需要注意的细节和“坑”
了解了基本原理后,在实际使用中还有一些细节需要注意,这些也是社区讨论中经常提到的问题:
- 过期事件的触发:Redis的键过期是“被动”的,意思是,一个键到期后,Redis不会主动发送通知告诉客户端“这个键过期了”,只有当客户端尝试去获取这个键时,才会触发惰性删除并发现它已过期,虽然Redis有发布订阅功能可以模拟键空间通知,但那需要额外配置和订阅,并且可靠性需要自己保证。
- 主从复制下的过期:在Redis主从架构中,过期键的删除操作是由主节点(Master)控制的,主节点在删除一个过期键后,会向所有从节点(Slave)发送一个
DEL命令,从节点自身不会主动删除过期键,它们只会被动接收主节点的指令,这是为了保持数据的一致性,由主节点统一决策。 - 持久化时的处理:当Redis进行数据持久化(RDB快照或AOF日志)时,也会处理过期键,生成RDB文件时,过期的键不会被保存到快照中,在载入RDB文件时,如果是主服务器模式,会检查键是否过期;如果是从服务器模式,则会全部载入,等待主节点同步DEL命令,AOF日志在重写(Rewrite)时,也会像生成RDB一样,忽略那些已经过期的键。
Redis通过过期字典精确记录每个键的“死期”,再结合惰性删除和定期删除这两种互补的策略,巧妙地平衡了性能和内存使用效率,使得处理海量数据的过期变得高效而实用,理解这些机制,能帮助我们在使用Redis设置过期时间时更加得心应手,避免踩坑。
本文由帖慧艳于2026-01-14发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/80810.html
