Redis过期那些事儿,聪明点用起来别慌乱,优雅解决各种坑
- 问答
- 2025-12-29 13:25:13
- 1
综合自多位资深开发者的实践经验总结及Redis官方文档的核心思想)
Redis过期那些事儿,聪明点用起来别慌乱,优雅解决各种坑
咱们用Redis,经常会把一些临时性的数据塞进去,比如短信验证码、用户登录的token、或者一些耗时的计算结果,这些东西总不能一直占着内存吧?所以就得给它们设个过期时间,这事儿听起来简单,不就是个EXPIRE命令嘛,但里头的小九九可不少,用不好轻则数据错乱,重则可能把系统搞挂,今天就来聊聊怎么聪明地用过期机制,避开那些常见的坑。
第一件事:过期时间怎么设?别想当然!
很多人觉得,设个过期时间,比如5分钟,那这个键一定会在5分钟整的时候准时被删除,这么想就太天真了,Redis删除过期键主要有两种策略,都不是“准时”的。
一种是惰性删除。(来源:Redis官方文档对过期机制的描述)简单说,就是当你去访问一个键的时候,Redis才会顺便检查一下它有没有过期,如果过期了,当场就把它删掉,然后返回一个空值给你,这就像你家里有个零食箱,只有你想去拿零食吃的时候,才会发现“哎哟,这包薯片过期了”,然后把它扔掉,如果一直没人去碰这个键,哪怕它早过期了,它也会一直赖在内存里占着地方。

另一种是定期删除。(来源:Redis官方文档对过期机制的描述)Redis会每隔一段时间(默认是100毫秒)随机抽查一批设置了过期时间的键,把其中已经过期的清理掉,因为它是随机抽查的,所以不可能检查所有键,总会有一些“漏网之鱼”。
你设的过期时间,更像是一个“最早被删除”的时间点,而不是一个精确的“死亡倒计时”,明白了这一点,你就不会奇怪为什么有时候数据好像多存在了一会儿。
第二件事:小心“缓存穿透”和“内存耗尽”的坑
惰性删除这个机制,如果遇上一些坏情况,可能会引来大麻烦,想象一个场景:有一个键过期了,但一直没人来访问它,你的Redis内存快要满了,这时候,Redis会启动它的内存淘汰机制(比如LRU,最近最少使用)来删掉一些键,腾出空间。(来源:对缓存穿透和雪崩问题的常见分析)但问题在于,内存淘汰机制可能删的是那些还在被频繁访问的“热key”,而那个早已过期的“僵尸key”却因为没人访问,躲过了淘汰机制,继续占着茅坑不拉屎,这就会导致内存使用率居高不下,甚至可能触发OOM(内存溢出),让Redis整个崩掉。

那怎么办呢?光靠Redis自己可能不够聪明,我们得主动一点。
-
对付顽固的僵尸key:可以写个简单的小脚本,定期用
SCAN命令扫描一下所有的键,用TTL命令检查它们的剩余存活时间,如果发现某个键的TTL是-1(表示没设过期时间)或者已经过期但还在(TTL为-2),就得引起警觉了,对于没设过期时间的,要考虑业务上是否需要补设;对于已过期的,可以强制删除,这叫主动清理,给内存做个大扫除。 -
对付缓存穿透:可能会有人恶意或者无意地频繁请求一个根本不存在的数据,这个数据在Redis里肯定没有,每次请求都会穿透到数据库去查,数据库压力巨大。(来源:常见的缓存解决方案)这时候,即使数据不存在,我们也可以把这个“空结果”也塞进Redis,并给它设一个很短的过期时间(比如30秒),这样,在短时间内再有相同的请求过来,就能在Redis层面被挡住,直接返回空,避免了数据库被冲垮,这叫“缓存空对象”策略。
第三件事:持久化时的过期键,别让数据“复活”

Redis为了数据安全,会把内存里的数据持久化到硬盘上,主要有RDB和AOF两种方式,过期键在持久化的时候是怎么处理的呢?(来源:Redis官方文档关于持久化与过期的说明)
- RDB快照:在创建RDB文件的时候,Redis会检查键是否过期,过期的键是不会被保存到RDB文件里的,当你用一个包含过期键的旧RDB文件恢复数据时,这些键是不会被加载回来的,这符合预期。
- AOF日志:AOF是记录所有写命令的,当一个键因为过期被删除时(无论是惰性删除还是定期删除),Redis会向AOF文件末尾追加一条
DEL命令,这样,在重启后用AOF文件恢复数据时,先还原了这个键,然后执行到后面的DEL命令又会把它删掉,最终结果也是这个键不存在。
这里有个细节要注意:如果你在Redis运行时,手动修改了系统时间,把它往回调了,可能会导致一些已经过期的键,因为新的当前时间比它的过期时间戳要早,而“误以为”自己还没过期,从而异常地“复活”一段时间。绝对不要在生产环境中随意修改服务器时间,这是个非常危险的操作。
第四件事:事务和脚本里的过期,行为有点微妙
如果你在Redis的事务(MULTI/EXEC)或者Lua脚本里操作一个键,事情会有点不一样。(来源:Redis官方文档关于事务中过期的说明)在事务的执行过程中,Redis不会主动去检查键是否过期,即使一个键在事务队列里等待执行的时候已经过期了,只要还没轮到执行操作它的那条命令,它就不会被惰性删除,它会一直撑到命令真正执行的那一刻,才会被检查并删除。
这意味着,你不能指望在事务里通过判断一个键是否存在(可能它已过期但未被删)来作为严格的逻辑条件,因为你的判断可能和实际情况有细微的偏差,对于要求强一致性的场景,这点要特别小心。
怎么才算聪明又优雅?
- 心里有数:知道过期删除不是准时的,是惰性+定期结合的,避免在业务逻辑里做精确的时间依赖。
- 主动管理:不要完全依赖Redis的自动机制,定期扫描和清理过期键或无用键,保持良好的内存习惯。
- 设计防御:用“缓存空对象”等策略预防缓存穿透,保护后端数据库。
- 规避风险:严禁随意修改服务器时间,防止过期逻辑混乱。
- 留意细节:在事务、脚本等复杂操作中,意识到过期检查的时机可能带来的影响。
把这些要点记在心里,你就能更从容地驾驭Redis的过期机制,让它真正成为你提升应用性能的利器,而不是半夜把你叫醒的坑货。
本文由寇乐童于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/70674.html
