Redis 过期与键删除

Redis 的键默认永久保存,而缓存类数据需要"存活一段时间后自动消失",这正是过期(TTL,生存时间)机制要解决的问题。给键设置过期时间后,Redis 会在到期时将其删除,常用于验证码、会话 Token、限流计数器、临时缓存等场景。

设置与查看过期时间

EXPIRE 以秒为单位设置过期时间,返回 1 表示设置成功,0 表示键不存在:

SET token "abc123"
# 输出:OK
EXPIRE token 60
# 输出:(integer) 1        # 60 秒后过期
TTL token
# 输出:(integer) 60       # 剩余秒数
PEXPIRE token 60000
# 输出:(integer) 1        # 毫秒级设置,可用于更精细的控制
PTTL token
# 输出:(integer) 59999    # 剩余毫秒数(数值随执行时刻略减)

TTL 有两个特殊返回值:-1 表示键没设过期(永久键),-2 表示键不存在。PERSIST 去掉过期时间让键变回永久:

PERSIST token
# 输出:(integer) 1        # 成功移除过期时间
TTL token
# 输出:(integer) -1       # 变回永久键

按绝对时间过期

EXPIREAT / PEXPIREAT 指定"到期时刻"(Unix 时间戳),适合一批数据统一在某个时刻失效:

EXPIREAT coupon:001 1900000000
# 输出:(integer) 1        # 到期时刻已设定
# 此后 TTL 随时间递减,归零时键被删除

写入时直接带过期

SET 支持 EX/PX 选项,"写值 + 设过期"一步完成,比先 SET 再 EXPIRE 少一次往返且天然原子:

SET captcha "8f3k" EX 300
# 输出:OK
TTL captcha
# 输出:(integer) 300

过期键是怎么被删除的

过期删除与内存淘汰

  • 惰性删除:键被访问(如 GET)时先检查是否过期,过期就顺手删除并返回空,保证读不到已过期的数据。
  • 定期删除:服务器以约每秒 10 次的频率运行过期循环,每次抽样一批设置了 TTL 的键,删除其中已过期的,避免过期键只在被访问时才清理、长期占用内存。

主从与集群中的过期

  • 主从复制:过期删除由主库执行,删掉后向从库发 DEL 同步删除;从库不按自己的时钟自行删键,避免主从时间不一致导致数据分叉。
  • 集群:每个节点负责自己槽位上的键,过期行为与单机一致。

常见坑

  • SET 覆盖旧值会清掉过期时间;而 INCR、LPUSH 这类"在原值上修改"的命令不会清 TTL。想刷新存活时间应重新 SET EX。
  • EXPIRE 不存在的键返回 0 但不报错;对已过期(尚未被物理删除)的键执行 EXPIRE 同样返回 0。
  • EXPIRE 传 0 或负数会立即删除键;EXPIREAT 传过去的时间戳同理。
  • 只有顶层键能设过期,Hash、List 等内部元素没有 TTL。
  • 大量键在同一刻过期会形成瞬时删除压力(缓存雪崩诱因之一),生产上常给过期时间加随机抖动,如 3600 + random(0, 600) 秒。

小结

过期机制 = 惰性删除 + 定期删除;命令上记住 EXPIRE/PEXPIRE、TTL/PTTL、PERSIST、EXPIREAT 与 SET EX 原子写法。缓存类键务必设合理 TTL,并提防"SET 覆盖清 TTL、大量同刻过期引发雪崩"这两个高频坑。

笔记加载中…