Redis过期时间怎么设置?TTL查看方法与常见坑点详解

来源:Webpack教程作者:深圳GEO公司头衔:草根站长
导读:本期聚焦于深圳GEO公司创作的《Redis过期时间怎么设置?TTL查看方法与常见坑点详解》,敬请观看详情。Redis中的key设置过期时间后到底什么时候会被删除?为什么明明设置了过期时间,用TTL命令查看却返回-1或-2?本文围绕Redis过期时间的几种设置方式展开,详细讲解EXPIRE、PEXPIRE、EXPIREAT等命令的区别,演示TTL与PTTL的返回值含义,并深入分析惰性删除与定期删除两种过期策略的工作原理。文中还会对比SET命令带EX参数与单独执行EXPIRE的原子性差异,给出持久化场景下RDB和AOF对过期key的处理方式,帮助读者彻底掌握Redis过期机制,避开开发中容易踩到的坑。

在Redis的实际使用中,给key设置过期时间是非常常见的操作,比如缓存自动失效、验证码五分钟有效、登录态保持七天等场景都离不开过期时间。但不少开发者对过期删除机制存在误解,以为到了时间key就会立刻消失,结果线上出现了内存占用异常或者读到已过期数据的问题。本文将系统讲解Redis中设置过期时间的各类命令、TTL查看方式的返回值含义,以及底层过期删除策略的原理。

Redis过期时间怎么设置?TTL查看方法与常见坑点详解

一、设置过期时间的几种命令

Redis提供了多个与过期时间相关的命令,最常用的是EXPIRE,它以秒为单位给已存在的key设置存活时间。与之对应的PEXPIRE则以毫秒为单位,适合需要更精细控制的场景。除了设定相对时间,Redis还支持设定绝对时间点,EXPIREAT接受一个Unix时间戳(秒),PEXPIREAT接受毫秒级时间戳,表示key在指定时刻过期。

127.0.0.1:6379> SET session:user1001 "abc"
OK
127.0.0.1:6379> EXPIRE session:user1001 300
(integer) 1
127.0.0.1:6379> PEXPIRE session:user1001 300000
(integer) 1
127.0.0.1:6379> EXPIREAT session:user1001 1735689600
(integer) 1
127.0.0.1:6379> PERSIST session:user1001
(integer) 1

需要注意的是,如果对一个不存在的key执行EXPIRE,命令会返回0而不是报错。另外PERSIST命令可以移除key的过期时间,让它变成永久key,执行成功返回1。还有一个容易忽略的细节:对已经设置过期时间的key再次执行EXPIRE,会重置过期时间为新的值,而不是保持原来的时间。

二、SET命令与EXPIRE的原子性问题

很多教程会教大家先用SET写入key,再调用EXPIRE设置过期时间。这种写法在单客户端环境下没有问题,但如果两条命令之间出现异常,比如应用崩溃或网络中断,就可能出现一个没有过期时间的永久key,长期积累会占满内存。为了解决这个问题,Redis从2.6.12版本开始允许在SET命令中直接携带过期参数。

127.0.0.1:6379> SET cache:product:88 "data" EX 3600
OK
127.0.0.1:6379> SET cache:product:88 "data" PX 60000 NX
OK

EX表示秒,PX表示毫秒,配合NXXX选项使用时也非常方便,例如实现分布式锁时常用的SET lock:key value NX EX 10就是一条原子命令。建议在业务代码中养成使用带过期参数的SET的习惯,避免两步操作带来的隐患。此外,对string类型还可以使用SETEXPSETEX这两个快捷命令,效果等同于SET加EXPIRE的组合,但功能上是原子的。

三、TTL与PTTL的返回值含义

设置过期时间之后,查看剩余存活时间使用TTL命令,返回值以秒为单位;PTTL则返回毫秒级精度。这两个命令的返回值有三种情况,理解清楚才能正确排查问题。

返回值含义
-2key不存在(从未创建或已被删除,包括已过期被回收)
-1key存在但没有设置过期时间,即永久key
大于0的整数剩余存活时间

特别要区分-1和-2的含义,这是排查问题时的常见困惑点。当你发现TTL返回-1,说明这个key不会自动过期,需要检查业务代码是否遗漏了过期设置,或者是否被PERSIST清除了过期时间。还有一个隐蔽的情况:某些命令执行后会清除key的过期时间,例如对list执行LPUSH或对string执行SET覆盖旧值,都会导致原本的过期时间被移除,key重新变成永久key。

127.0.0.1:6379> SET code:phone138 "123456" EX 300
OK
127.0.0.1:6379> TTL code:phone138
(integer) 298
127.0.0.1:6379> GET code:phone138
"123456"
127.0.0.1:6379> SET code:phone138 "654321"
OK
127.0.0.1:6379> TTL code:phone138
(integer) -1

上面的例子清楚地展示了覆盖写入后过期时间丢失的过程。验证码场景中如果不注意这一点,可能出现验证码长期有效的安全漏洞,正确做法是每次写入都带上EX参数。

四、过期key的删除策略与内存影响

很多人以为过期时间一到Redis会立刻删除key,实际上Redis采用的是惰性删除与定期删除相结合的策略。惰性删除是指当客户端访问某个key时,Redis先检查它是否已过期,如果过期就立即删除并返回空结果。这种方式的问题是,如果一个key过期后始终没有被访问,它会一直残留在内存中。

为了弥补这个缺陷,Redis还会定期删除:默认每秒执行10次(可通过hz参数调整),每次从设置了过期时间的key中随机抽取一部分检查,删除其中已过期的。如果这一轮过期key的比例超过25%,会继续抽查,形成一个自适应的循环。这种设计在CPU占用和内存回收效率之间做了平衡。

在集群和主从复制场景下还有更多细节:从节点不会主动删除过期key,而是等待主节点删除后同步DEL命令,因此读取从节点时如果发现key已过期,会直接返回空而不返回value。在持久化方面,RDB快照保存时会把已过期的key跳过,载入时也会忽略过期key;AOF重写时同样会剔除过期key,但AOF追加阶段如果key过期被删除,会记录一条DEL命令保证一致性。理解这些机制,有助于在内存暴涨或数据不一致问题出现时快速定位是否与过期策略有关。

五、实践建议与常见坑总结

综合上面的原理分析,给出几条实践建议。第一,所有缓存类key务必设置过期时间,避免内存无限增长,即使业务上不确定合适的时长,也建议设置一个兜底值。第二,写代码时优先使用SET key value EX seconds的原子写法,而不是SET加EXPIRE两步操作。第三,排查问题时先看TTL返回值,-1和-2分别指向不同的原因,不要混为一谈。

第四,注意覆盖操作会重置过期时间这个特性,特别是在更新缓存内容时,记得每次更新都显式带上过期参数。第五,如果需要批量查看key的剩余时间,Redis没有原生的批量TTL命令,可以在客户端用pipeline循环执行TTL,减少网络往返开销。第六,对于要求精确到某一时刻过期的业务(如秒杀活动结束),使用EXPIREAT比计算相对秒数更直观也更不容易出错。

掌握Redis过期时间的设置与查看方法,不仅是记住几条命令,更重要的是理解背后的删除策略与各种边界行为。这样才能在缓存设计、内存治理等场景中做出正确的决策,避免线上问题。

Redis过期时间Redis TTLRedis key过期策略修改时间:2026-09-01 04:20:53

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。