Redis里控制数据过期时间和设置响应的那些事儿,怎么用才更有效率
- 问答
- 2025-12-24 13:37:01
- 4
在Redis里,给数据设置过期时间是一个非常核心且好用的功能,它让你不用再手动去删除那些临时数据,比如短信验证码、用户登录令牌、或者是一些临时的缓存结果,Redis会自动帮你清理掉过期的数据,省心省力,用得好和用得不好,效率差别很大,这其中的门道,主要围绕几个命令和它们背后的原理。
核心命令:EXPIRE 和 PEXPIRE
最常用的设置过期时间的命令就是EXPIRE和PEXPIRE了,根据Redis官方文档(Redis Commands)的说明,它们的区别很简单:
EXPIRE key seconds:给一个键设置以秒为单位的存活时间,比如EXPIRE sms_code:13800138000 300,就是让这个键在300秒(5分钟)后自动过期。PEXPIRE key milliseconds:和EXPIRE一样,但时间单位是毫秒,用于需要更精确控制的场景,比如PEXPIRE temp_lock 1500就是1.5秒后过期。
设置成功后,你可以用TTL key命令来查看这个键还剩下多少秒存活时间,用PTTL key则是查看毫秒数,如果返回-2,表示这个键已经不存在了;如果返回-1,表示这个键存在但没有设置过期时间。
设置键的同时就设置过期时间:SET的附加选项
很多人习惯先用SET命令存数据,然后再用EXPIRE命令去设置时间,这其实是两次网络通信,对于追求高效率的应用来说,是一种浪费,更高效的做法是使用SET命令自带的过期选项,根据Redis官方文档对SET命令的详细描述,你可以直接这样写:
SET key value EX seconds 或者 SET key value PX milliseconds。
SET session:user123 "user_data" EX 3600,这一条命令就完成了设置值和设置3600秒过期时间两个操作,只需要一次网络往返,效率更高,这是提升效率的第一个关键点。
过期键是如何被删除的?惰性删除和定期删除
理解了Redis是怎么处理过期键的,你才能更好地使用它,Redis采用了两种策略结合的方式,这在Redis官方文档关于过期(Expire)的章节里有明确解释:
-
惰性删除:当客户端尝试访问一个键时,Redis会先检查这个键是否设置了过期时间,以及是否已经过期,如果过期了,Redis会立刻删除它,然后返回空值,就像这个键不存在一样,这种策略的好处是,CPU时间只用在实际被访问的键上,不会在无人问津的过期键上浪费资源,但坏处是,如果一个键永远不再被访问,即使它早已过期,也会一直占用着内存,成为“垃圾数据”。
-
定期删除:为了解决惰性删除可能造成的内存浪费问题,Redis会定期地(通常是每秒10次,可配置)主动随机测试一批设置了过期时间的键,它会从相关的过期字典中随机抽取少量键(比如20个),检查并删除其中已过期的,如果这批键中过期的比例很高,它就再随机抽取一批,继续这个过程,直到过期键的比例降下来,这种方式是系统在后台悄悄进行的,是对惰性删除的有效补充。
你可能会发现,一个键虽然过期了,但并没有在精确的时间点被删除,而是稍后才被清理掉,这对于大多数应用来说是可以接受的,但如果你需要非常精确的过期判断,就需要在业务逻辑层面做补充,比如在读取数据时,应用代码自己再检查一次时间戳。
如何用得更有效率?
基于上面的原理,我们可以总结出几个提升效率的要点:
-
优先使用带过期时间的SET命令:如前所述,
SET key value EX seconds比先SET后EXPIRE更高效,减少了一次网络通信。 -
警惕大量键同时过期:这是一个非常经典的坑,如果你有成千上万的键在同一个秒级时刻过期(比如在凌晨零点,很多缓存数据同时失效),Redis的定期删除任务会在那一刻变得非常繁重,更重要的是,当这些键失效后,大量的用户请求会因缓存失效(通常称为“缓存击穿”)而直接打到后端数据库上,瞬间可能导致数据库压力过大而瘫痪。
- 解决方案:给过期时间加上一个随机扰动,原本都设置在一小时后过期,你可以改成在1小时的基础上,加上一个0到300秒的随机值,这样,键的过期时间就分散开了,避免了“雪崩”效应。
-
合理使用PERSIST命令:
PERSIST key命令可以移除一个键的过期时间,让其永久保存,这在某些场景下有用,比如一个临时任务升级为永久状态,但要谨慎使用,避免意外导致本该过期的数据常驻内存。 -
对于更新操作,注意过期时间的处理:当你用新值覆盖一个已经存在的键时(例如再次使用
SET),默认情况下原有的过期时间会被清除,键将变成永久的,除非你在新的SET命令里重新指定过期时间,这是一个容易忽略的细节,如果你希望更新值但保持原有的过期时间逻辑,一个办法是先用TTL查询剩余时间,然后用这个剩余时间作为新SET命令的过期参数,如果业务允许,更简单的做法是每次都设置一个固定的、合理的过期时间。 -
选择合适的数据结构:有时我们需要的不是整个大Key过期,而是大Key里面的某个字段过期,比如一个存储用户信息的Hash,你只想让里面的“认证状态”过期,原生Redis不支持这种字段级过期,但你可以通过一些设计来模拟,比如将需要过期的字段值本身也设为一个单独的键,并为其设置过期时间,然后在主结构中存储这个键名,虽然复杂了些,但在特定场景下能节省大量内存和网络传输。
Redis的过期机制非常强大,但“神器”要用好,就得了解它的脾气,核心就是:合并操作减少网络开销、分散过期时间避免集中冲击、理解删除原理设置合理预期,做到这几点,你使用Redis过期功能的效率就会高很多。

本文由召安青于2025-12-24发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/67576.html
