Redis命令:EXPIRETIME
Redis EXPIRETIME 命令详细教程
EXPIRETIME用于获取 Key 的过期时间对应的 Unix 时间戳(秒)。与TTL返回剩余秒数不同,EXPIRETIME返回的是绝对时间点,便于在应用端直接判断 Key 何时过期、进行倒计时或与定时任务结合使用。
本文基于 Redis 通用 Key 操作介绍
EXPIRETIME。Redis 命令本身不区分大小写,因此EXPIRETIME、expiretime和Expiretime的效果相同;文档统一使用大写形式。EXPIRETIME自 Redis 7.0 起可用。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、命令概览
1. 基本语法
EXPIRETIME key参数说明:
| 参数 | 说明 |
|---|---|
key | 要查询过期时间戳的 Key |
返回值:
| 场景 | 返回值 |
|---|---|
| Key 存在且有过期时间 | 过期时间的 Unix 时间戳(正整数,秒) |
| Key 存在但无过期时间(永久有效) | -1 |
| Key 不存在 | -2 |
2. 最简单的示例
先写入一个值并设置过期时间,再查看过期时间戳:
SET mykey "Hello" EX 3600 EXPIRETIME mykey返回类似:
(integer) 1724719123返回值是该 Key 过期时刻的 Unix 时间戳(秒)。用当前时间戳减去它,结果等于TTL的值。
二、EXPIRETIME 的返回结果
1. Key 存在且有过期时间
SET session:user:1001 "active" EX 1800 EXPIRETIME session:user:1001返回一个正整数,如(integer) 1724722723,表示该 Key 将在该 Unix 时间戳对应的时刻过期。
2. Key 存在但无过期时间(永久有效)
SET permanent-key "forever" EXPIRETIME permanent-key返回:
(integer) -1-1表示 Key 存在但没有设置过期时间,永远不会自动过期。
3. Key 不存在
EXPIRETIME no-such-key返回:
(integer) -2-2表示 Key 不存在(可能从未创建、已被删除或已过期被清理)。
4. 已过期的 Key
已经过期但尚未被惰性/定期删除清理的 Key,EXPIRETIME返回-2(视为不存在):
SET temp-key "value" EX 1等待 1 秒后执行:
EXPIRETIME temp-key返回:
(integer) -2Redis 在访问时进行惰性过期检查,因此即使 Key 尚在内存中,EXPIRETIME也会正确返回-2。
5. 用绝对时间戳设置过期的 Key
使用EXPIREAT或SET ... EXAT设置的 Key,EXPIRETIME返回的值就是设置时指定的时间戳:
SET promo:key "summer-sale" EXAT 1735689600 EXPIRETIME promo:key返回:
(integer) 1735689600用相对时间设置的 Key,返回值也是绝对时间戳,而非相对秒数:
SET cache:key "value" EX 3600 EXPIRETIME cache:key返回的是"当前时间 + 3600 秒"对应的绝对时间戳。
三、EXPIRETIME 与 TTL 的关系
EXPIRETIME返回过期时刻的绝对时间戳,TTL返回剩余生存秒数。两者存在数学关系:
TTL(key) = EXPIRETIME(key) - 当前Unix时间戳1. 对比示例
SET mykey "value" EX 3600 TTL mykey EXPIRETIME mykey TIME返回类似:
TTL mykey -> (integer) 3600 EXPIRETIME mykey -> (integer) 1724722723 TIME -> 1) "1724719123" 2) "456789"验证:1724722723 - 1724719123 = 3600,与TTL返回值一致。
2. 何时使用 EXPIRETIME,何时使用 TTL
| 需求 | 推荐命令 | 原因 |
|---|---|---|
| 判断 Key 是否快过期 | TTL | 直接得到剩余秒数 |
| 显示倒计时 | TTL | 剩余秒数可直接用于倒计时 |
| 获取 Key 何时过期(绝对时间) | EXPIRETIME | 返回绝对时间戳 |
| 与外部定时任务结合 | EXPIRETIME | 绝对时间便于跨系统对齐 |
| 判断 Key 是永久还是临时 | TTL或EXPIRETIME | 均可,返回-1即永久 |
四、EXPIRETIME 与相关命令的区别
1. EXPIRETIME 与 PEXPIRETIME
EXPIRETIME返回秒级时间戳,PEXPIRETIME返回毫秒级时间戳:
SET mykey "value" PEX 3600000 EXPIRETIME mykey # 返回秒级时间戳,如 1724722723 PEXPIRETIME mykey # 返回毫秒级时间戳,如 1724722723456| 命令 | 精度 | 返回值示例 |
|---|---|---|
EXPIRETIME key | 秒 | 1724722723 |
PEXPIRETIME key | 毫秒 | 1724722723456 |
需要毫秒精度时使用PEXPIRETIME。
2. EXPIRETIME 与 TTL / PTTL
| 命令 | 返回内容 | 单位 |
|---|---|---|
EXPIRETIME key | 过期时刻的绝对时间戳 | 秒 |
PEXPIRETIME key | 过期时刻的绝对时间戳 | 毫秒 |
TTL key | 剩余生存时间 | 秒 |
PTTL key | 剩余生存时间 | 毫秒 |
SET mykey "value" EX 3600 EXPIRETIME mykey # 过期时间戳 TTL mykey # 剩余秒数 PTTL mykey # 剩余毫秒数 PEXPIRETIME mykey # 过期毫秒时间戳3. EXPIRETIME 与 EXPIREAT / EXPIRE 的区别
EXPIREAT和EXPIRE是写命令,用于设置过期时间;EXPIRETIME是只读命令,用于查询过期时间戳。
| 命令 | 操作类型 | 作用 |
|---|---|---|
EXPIREAT key timestamp | 写 | 设置绝对过期时间 |
EXPIRE key seconds | 写 | 设置相对过期时间 |
EXPIRETIME key | 只读 | 查询过期时间戳 |
4. 返回值对比总表
| 状态 | EXPIRETIME | TTL | PTTL | PEXPIRETIME |
|---|---|---|---|---|
| Key 存在且有过期 | 过期秒级时间戳 | 剩余秒数 | 剩余毫秒数 | 过期毫秒级时间戳 |
| Key 存在无过期 | -1 | -1 | -1 | -1 |
| Key 不存在 | -2 | -2 | -2 | -2 |
五、EXPIRETIME 与不同数据类型
EXPIRETIME作用于整个 Key,所有数据类型(String、Hash、List、Set、Sorted Set、Stream 等)的行为一致。
HSET user:1001 name "Alice" age 30 EXPIRE user:1001 3600 EXPIRETIME user:1001RPUSH queue:jobs job-a job-b EXPIRE queue:jobs 1800 EXPIRETIME queue:jobsSADD tags redis python EXPIRE tags 7200 EXPIRETIME tags返回值都是 Key 的过期时间戳,与数据类型无关。
六、过期时间的刷新与 EXPIRETIME
1. 覆盖式更新后的反映
对已有过期时间的 Key 再次执行EXPIRE或EXPIREAT,EXPIRETIME返回的值会更新为新的过期时间戳:
SET mykey "value" EX 3600 EXPIRETIME mykey # 返回 timestamp1 EXPIREAT mykey 1767225600 EXPIRETIME mykey # 返回 17672256002. SET 会清除过期时间
使用SET命令覆盖 Key 的值时(不带EX/PX/EXAT/PXAT),过期时间被清除,EXPIRETIME返回-1:
SET mykey "old" EX 3600 EXPIRETIME mykey # 返回正数 SET mykey "new" EXPIRETIME mykey # 返回 -13. PERSIST 后的反映
PERSIST移除过期时间后,EXPIRETIME返回-1:
SET mykey "value" EX 3600 PERSIST mykey EXPIRETIME mykey # 返回 -14. 各命令对 EXPIRETIME 结果的影响
| 操作 | EXPIRETIME 返回值变化 |
|---|---|
EXPIRE key seconds | 更新为新的过期时间戳 |
EXPIREAT key timestamp | 更新为指定的时间戳 |
PEXPIRE key ms | 更新为新的过期时间戳 |
PEXPIREAT key timestamp | 更新为指定的时间戳 |
SET key value(无选项) | 变为-1(清除过期) |
SET key value EX seconds | 更新为新的过期时间戳 |
SET key value EXAT timestamp | 更新为指定的时间戳 |
PERSIST key | 变为-1(移除过期) |
INCR/LPUSH/HSET等 | 不影响,保持原值 |
GETEX key | 取决于参数,可修改或清除过期时间 |
七、事务、Pipeline 与并发场景
1. 在事务中使用
EXPIRETIME可以放入事务队列:
MULTI SET mykey "value" EX 3600 EXPIRETIME mykey TTL mykey EXECEXEC执行后返回各命令的结果。
2. 只读特性与并发安全
EXPIRETIME是只读命令,不修改任何数据,不会影响其他客户端的操作。多个客户端同时调用EXPIRETIME是安全的。
3. 并发场景下的注意事项
由于EXPIRETIME返回的是查询时刻的过期时间戳,如果在两次查询之间有其他客户端修改了 Key 的过期时间(如EXPIRE、SET、PERSIST),返回值可能不同。这属于正常的并发行为,"先查再判断"的多步流程不是原子操作。
需要原子地"检查过期时间并执行操作"时,使用 Lua 脚本:
localexpire=redis.call("EXPIRETIME",KEYS[1])ifexpire>0thenreturnexpireelsereturnredis.call("EXPIRE",KEYS[1],ARGV[1])end4. Pipeline 批量查询
需要查询大量 Key 的过期时间戳时,可以使用 Pipeline 批量发送EXPIRETIME命令,减少网络往返。
八、在常见客户端中的使用方式
1. redis-cli
redis-cli SET mykey"value"EX3600redis-cli EXPIRETIME mykey redis-cli SET permanent"forever"redis-cli EXPIRETIME permanent redis-cli EXPIRETIME no-such-key分别返回:正数时间戳、-1、-2。
2. Python(redis-py)
importredis client=redis.Redis(host="localhost",port=6379,decode_responses=True)client.set("mykey","value",ex=3600)# 获取过期时间戳expire_time=client.expiretime("mykey")print(expire_time)# 如 1724722723# 永久 Keyclient.set("permanent","forever")print(client.expiretime("permanent"))# -1# 不存在的 Keyprint(client.expiretime("no-such-key"))# -23. Node.js(node-redis)
import{createClient}from"redis";constclient=createClient();awaitclient.connect();awaitclient.set("mykey","value",{EX:3600});constexpireTime=awaitclient.expireTime("mykey");console.log(expireTime);// 如 1724722723awaitclient.set("permanent","forever");console.log(awaitclient.expireTime("permanent"));// -1console.log(awaitclient.expireTime("no-such-key"));// -2awaitclient.quit();4. Java(Jedis)
try(Jedisjedis=newJedis("localhost",6379)){jedis.set("mykey","value",SetParams.setParams().ex(3600));// 获取过期时间戳longexpireTime=jedis.expireTime("mykey");System.out.println(expireTime);// 如 1724722723// 永久 Keyjedis.set("permanent","forever");System.out.println(jedis.expireTime("permanent"));// -1// 不存在的 KeySystem.out.println(jedis.expireTime("no-such-key"));// -2}九、典型使用场景
1. 倒计时显示
获取 Key 的绝对过期时间戳,在客户端计算剩余时间并显示倒计时:
SET flash-sale:product "active" EX 3600 EXPIRETIME flash-sale:product客户端用EXPIRETIME返回的时间戳减去当前时间戳,得到剩余秒数并显示。
2. 过期时间对齐
多个 Key 需要在同一时刻过期时,用EXPIRETIME确认是否已对齐:
EXPIRETIME cache:a EXPIRETIME cache:b EXPIRETIME cache:c如果返回值不同,用EXPIREAT统一调整:
EXPIREAT cache:a 1735689600 EXPIREAT cache:b 1735689600 EXPIREAT cache:c 17356896003. 监控与告警
监控系统查询 Key 的过期时间戳,判断是否即将过期并提前告警:
EXPIRETIME session:critical如果返回的时间戳接近当前时间戳,触发告警提醒续期。
4. 与外部定时任务结合
应用端获取 Key 的过期时间戳后,在对应时刻注册定时任务处理过期事件:
EXPIRETIME task:cleanup5. 数据生命周期审计
定期扫描设置了过期时间的 Key,审计过期时间是否合理:
SCAN 0 EXPIRETIME key1 EXPIRETIME key2十、性能与使用建议
- 时间复杂度:O(1)。
EXPIRETIME是只读命令(ACL 类别为@keyspace、@read、@fast),不会修改数据,不会触发通知。- 性能优异,频繁调用不会对 Redis 造成压力。
- 只需判断 Key 是否存在时,用
EXISTS语义更清晰;需要过期时间信息时用EXPIRETIME。 - 需要剩余秒数时用
TTL,需要绝对时间戳时用EXPIRETIME,两者可互相换算。 EXPIRETIME对永久 Key 返回-1、对不存在的 Key 返回-2,与TTL的返回值约定一致,便于统一处理。- 集群模式下,
EXPIRETIME作用于单个 Key,不受哈希槽限制。 - Redis 7.0 以下版本不支持
EXPIRETIME,调用会返回错误。低版本场景可用TTL加上当前时间戳间接计算。
十一、常见问题排查
问题 1:EXPIRETIME 返回 -2 但 Key 应该存在
按以下顺序检查:
- 是否连接到了正确的 Redis 实例、端口和逻辑数据库(不同
SELECT库中 Key 相互独立)。 - Key 是否已经过期(用
TTL确认,返回-2表示不存在)。 - Key 名称是否包含不可见字符、前后空格或大小写差异。
- Key 是否被其他客户端删除或覆盖(
SET不带选项会清除过期时间但 Key 仍存在;如果返回-2则 Key 本身不存在)。
EXISTS mykey TTL mykey TYPE mykey问题 2:EXPIRETIME 返回 -1 但预期有过期时间
可能的原因:
- 在设置过期时间后,执行了
SET(不带EX/EXAT等选项)覆盖了 Key 的值,导致过期时间被清除。 - 执行了
PERSIST命令移除了过期时间。 - 查询的 Key 与设置过期的 Key 不是同一个(名称差异)。
问题 3:EXPIRETIME 返回的时间戳与预期不符
可能的原因:
- 使用了
EXPIRE(相对秒数)而非EXPIREAT(绝对时间戳)设置过期,返回的时间戳是"设置时刻 + 相对秒数"。 - 过期时间被其他客户端用
EXPIRE、EXPIREAT或SET ... EX更新过。 - 时区理解错误:返回的是 UTC Unix 时间戳,不是本地时间。
问题 4:Redis 7.0 以下版本报错
EXPIRETIME从 Redis 7.0 开始支持。低版本调用会返回错误:
ERR unknown command 'EXPIRETIME'替代方案:使用TTL key获取剩余秒数,加上当前时间戳得到过期时间戳:
redis-cli TTL mykey# 获取剩余秒数redis-cli TIME# 获取当前时间戳# 过期时间戳 = 当前时间戳 + TTL问题 5:EXPIRETIME 与 PEXPIRETIME 返回值不一致
EXPIRETIME返回秒级时间戳,PEXPIRETIME返回毫秒级时间戳。两者数值相差约 1000 倍,但表示的是同一过期时刻:
EXPIRETIME mykey # 如 1724722723 PEXPIRETIME mykey # 如 1724722723456PEXPIRETIME = EXPIRETIME * 1000 + 毫秒部分。
十二、完整练习
下面的示例演示从设置过期时间、查询过期时间戳、对比 TTL 与 EXPIRETIME、验证不同状态返回值,到与SET、PERSIST、EXPIREAT等命令配合使用的完整流程:
DEL demo:key DEL demo:perm DEL demo:short # 基本用法:设置相对过期,查询绝对时间戳 SET demo:key "hello" EX 3600 EXPIRETIME demo:key TTL demo:key TIME # 验证关系:EXPIRETIME = 当前时间戳 + TTL # 如 EXPIRETIME=1724722723, TIME=1724719123, TTL=3600 # 永久 Key 返回 -1 SET demo:perm "forever" EXPIRETIME demo:perm TTL demo:perm # 不存在的 Key 返回 -2 EXPIRETIME demo:noexist TTL demo:noexist # 用绝对时间戳设置过期 EXPIREAT demo:key 1767225600 EXPIRETIME demo:key # SET 清除过期时间 SET demo:key "new value" EXPIRETIME demo:key # SET ... EXAT 设置过期时间戳 SET demo:key "with ttl" EXAT 1735689600 EXPIRETIME demo:key # PERSIST 后返回 -1 PERSIST demo:key EXPIRETIME demo:key # 过期后返回 -2 SET demo:short "gone" EX 1 # 等待 1 秒后执行: # EXPIRETIME demo:short # TTL demo:short # 对比 EXPIRETIME 与 PEXPIRETIME SET demo:precision "value" EX 3600 EXPIRETIME demo:precision PEXPIRETIME demo:precision预期结果:
EXPIRETIME demo:key返回正数时间戳,TTL demo:key返回约3600,EXPIRETIME - TIME约等于TTL。EXPIRETIME demo:perm返回-1,TTL demo:perm返回-1。EXPIRETIME demo:noexist返回-2,TTL demo:noexist返回-2。EXPIREAT demo:key 1767225600后EXPIRETIME demo:key返回1767225600。SET demo:key "new value"后EXPIRETIME demo:key返回-1。SET demo:key "with ttl" EXAT 1735689600后EXPIRETIME demo:key返回1735689600。PERSIST demo:key后EXPIRETIME demo:key返回-1。- 过期后
EXPIRETIME demo:short返回-2。 EXPIRETIME与PEXPIRETIME返回值相差约 1000 倍,表示同一过期时刻。
十三、命令速查表
| 需求 | 命令 | 返回值类型 |
|---|---|---|
| 获取过期时间戳(秒) | EXPIRETIME key | 秒级 Unix 时间戳 |
| 获取过期时间戳(毫秒) | PEXPIRETIME key | 毫秒级 Unix 时间戳 |
| 获取剩余生存时间(秒) | TTL key | 剩余秒数 |
| 获取剩余生存时间(毫秒) | PTTL key | 剩余毫秒数 |
| 判断 Key 是否存在 | EXISTS key | 0 或 1 |
| 获取 Key 的数据类型 | TYPE key | 类型字符串 |
| 设置秒级过期时间 | EXPIRE key seconds | 0 或 1 |
| 设置绝对过期时间(秒) | EXPIREAT key timestamp | 0 或 1 |
| 设置毫秒级过期时间 | PEXPIRE key ms | 0 或 1 |
| 设置绝对过期时间(毫秒) | PEXPIREAT key timestamp | 0 或 1 |
| 原子设置值和过期时间戳 | SET key value EXAT timestamp | OK |
| 移除过期时间 | PERSIST key | 0 或 1 |
| 获取服务器当前时间 | TIME | 秒 + 微秒 |
总结
EXPIRETIME的核心作用是返回 Key 过期时刻的 Unix 时间戳(秒),便于应用端获取绝对过期时间点:
EXPIRETIME key使用时重点注意四点:
- 返回值约定与
TTL一致:正数表示过期时间戳,-1表示永久有效,-2表示 Key 不存在。 EXPIRETIME返回的是绝对时间戳,TTL返回的是剩余秒数,两者可互相换算。SET(不带选项)会清除过期时间,EXPIRE/EXPIREAT会更新过期时间,PERSIST会移除过期时间,EXPIRETIME能反映这些变化。EXPIRETIME从 Redis 7.0 开始支持,低版本可用TTL加当前时间戳间接计算过期时间戳。
