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、大量同刻过期引发雪崩"这两个高频坑。