当前位置: 首页 > news >正文

Redis命令:EXPIRETIME

Redis EXPIRETIME 命令详细教程

EXPIRETIME用于获取 Key 的过期时间对应的 Unix 时间戳(秒)。与TTL返回剩余秒数不同,EXPIRETIME返回的是绝对时间点,便于在应用端直接判断 Key 何时过期、进行倒计时或与定时任务结合使用。

本文基于 Redis 通用 Key 操作介绍EXPIRETIME。Redis 命令本身不区分大小写,因此EXPIRETIMEexpiretimeExpiretime的效果相同;文档统一使用大写形式。EXPIRETIME自 Redis 7.0 起可用。

资料合集:https://pan.quark.cn/s/10e98d308913https://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) -2

Redis 在访问时进行惰性过期检查,因此即使 Key 尚在内存中,EXPIRETIME也会正确返回-2

5. 用绝对时间戳设置过期的 Key

使用EXPIREATSET ... 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 是永久还是临时TTLEXPIRETIME均可,返回-1即永久

四、EXPIRETIME 与相关命令的区别

1. EXPIRETIME 与 PEXPIRETIME

EXPIRETIME返回秒级时间戳,PEXPIRETIME返回毫秒级时间戳:

SET mykey "value" PEX 3600000 EXPIRETIME mykey # 返回秒级时间戳,如 1724722723 PEXPIRETIME mykey # 返回毫秒级时间戳,如 1724722723456
命令精度返回值示例
EXPIRETIME key1724722723
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 的区别

EXPIREATEXPIRE是写命令,用于设置过期时间;EXPIRETIME是只读命令,用于查询过期时间戳。

命令操作类型作用
EXPIREAT key timestamp设置绝对过期时间
EXPIRE key seconds设置相对过期时间
EXPIRETIME key只读查询过期时间戳

4. 返回值对比总表

状态EXPIRETIMETTLPTTLPEXPIRETIME
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:1001
RPUSH queue:jobs job-a job-b EXPIRE queue:jobs 1800 EXPIRETIME queue:jobs
SADD tags redis python EXPIRE tags 7200 EXPIRETIME tags

返回值都是 Key 的过期时间戳,与数据类型无关。

六、过期时间的刷新与 EXPIRETIME

1. 覆盖式更新后的反映

对已有过期时间的 Key 再次执行EXPIREEXPIREATEXPIRETIME返回的值会更新为新的过期时间戳:

SET mykey "value" EX 3600 EXPIRETIME mykey # 返回 timestamp1 EXPIREAT mykey 1767225600 EXPIRETIME mykey # 返回 1767225600

2. SET 会清除过期时间

使用SET命令覆盖 Key 的值时(不带EX/PX/EXAT/PXAT),过期时间被清除,EXPIRETIME返回-1

SET mykey "old" EX 3600 EXPIRETIME mykey # 返回正数 SET mykey "new" EXPIRETIME mykey # 返回 -1

3. PERSIST 后的反映

PERSIST移除过期时间后,EXPIRETIME返回-1

SET mykey "value" EX 3600 PERSIST mykey EXPIRETIME mykey # 返回 -1

4. 各命令对 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 EXEC

EXEC执行后返回各命令的结果。

2. 只读特性与并发安全

EXPIRETIME是只读命令,不修改任何数据,不会影响其他客户端的操作。多个客户端同时调用EXPIRETIME是安全的。

3. 并发场景下的注意事项

由于EXPIRETIME返回的是查询时刻的过期时间戳,如果在两次查询之间有其他客户端修改了 Key 的过期时间(如EXPIRESETPERSIST),返回值可能不同。这属于正常的并发行为,"先查再判断"的多步流程不是原子操作。

需要原子地"检查过期时间并执行操作"时,使用 Lua 脚本:

localexpire=redis.call("EXPIRETIME",KEYS[1])ifexpire>0thenreturnexpireelsereturnredis.call("EXPIRE",KEYS[1],ARGV[1])end

4. 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"))# -2

3. 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 1735689600

3. 监控与告警

监控系统查询 Key 的过期时间戳,判断是否即将过期并提前告警:

EXPIRETIME session:critical

如果返回的时间戳接近当前时间戳,触发告警提醒续期。

4. 与外部定时任务结合

应用端获取 Key 的过期时间戳后,在对应时刻注册定时任务处理过期事件:

EXPIRETIME task:cleanup

5. 数据生命周期审计

定期扫描设置了过期时间的 Key,审计过期时间是否合理:

SCAN 0 EXPIRETIME key1 EXPIRETIME key2

十、性能与使用建议

  1. 时间复杂度:O(1)。
  2. EXPIRETIME是只读命令(ACL 类别为@keyspace@read@fast),不会修改数据,不会触发通知。
  3. 性能优异,频繁调用不会对 Redis 造成压力。
  4. 只需判断 Key 是否存在时,用EXISTS语义更清晰;需要过期时间信息时用EXPIRETIME
  5. 需要剩余秒数时用TTL,需要绝对时间戳时用EXPIRETIME,两者可互相换算。
  6. EXPIRETIME对永久 Key 返回-1、对不存在的 Key 返回-2,与TTL的返回值约定一致,便于统一处理。
  7. 集群模式下,EXPIRETIME作用于单个 Key,不受哈希槽限制。
  8. Redis 7.0 以下版本不支持EXPIRETIME,调用会返回错误。低版本场景可用TTL加上当前时间戳间接计算。

十一、常见问题排查

问题 1:EXPIRETIME 返回 -2 但 Key 应该存在

按以下顺序检查:

  1. 是否连接到了正确的 Redis 实例、端口和逻辑数据库(不同SELECT库中 Key 相互独立)。
  2. Key 是否已经过期(用TTL确认,返回-2表示不存在)。
  3. Key 名称是否包含不可见字符、前后空格或大小写差异。
  4. Key 是否被其他客户端删除或覆盖(SET不带选项会清除过期时间但 Key 仍存在;如果返回-2则 Key 本身不存在)。
EXISTS mykey TTL mykey TYPE mykey

问题 2:EXPIRETIME 返回 -1 但预期有过期时间

可能的原因:

  1. 在设置过期时间后,执行了SET(不带EX/EXAT等选项)覆盖了 Key 的值,导致过期时间被清除。
  2. 执行了PERSIST命令移除了过期时间。
  3. 查询的 Key 与设置过期的 Key 不是同一个(名称差异)。

问题 3:EXPIRETIME 返回的时间戳与预期不符

可能的原因:

  1. 使用了EXPIRE(相对秒数)而非EXPIREAT(绝对时间戳)设置过期,返回的时间戳是"设置时刻 + 相对秒数"。
  2. 过期时间被其他客户端用EXPIREEXPIREATSET ... EX更新过。
  3. 时区理解错误:返回的是 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 # 如 1724722723456

PEXPIRETIME = EXPIRETIME * 1000 + 毫秒部分

十二、完整练习

下面的示例演示从设置过期时间、查询过期时间戳、对比 TTL 与 EXPIRETIME、验证不同状态返回值,到与SETPERSISTEXPIREAT等命令配合使用的完整流程:

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返回约3600EXPIRETIME - TIME约等于TTL
  • EXPIRETIME demo:perm返回-1TTL demo:perm返回-1
  • EXPIRETIME demo:noexist返回-2TTL demo:noexist返回-2
  • EXPIREAT demo:key 1767225600EXPIRETIME demo:key返回1767225600
  • SET demo:key "new value"EXPIRETIME demo:key返回-1
  • SET demo:key "with ttl" EXAT 1735689600EXPIRETIME demo:key返回1735689600
  • PERSIST demo:keyEXPIRETIME demo:key返回-1
  • 过期后EXPIRETIME demo:short返回-2
  • EXPIRETIMEPEXPIRETIME返回值相差约 1000 倍,表示同一过期时刻。

十三、命令速查表

需求命令返回值类型
获取过期时间戳(秒)EXPIRETIME key秒级 Unix 时间戳
获取过期时间戳(毫秒)PEXPIRETIME key毫秒级 Unix 时间戳
获取剩余生存时间(秒)TTL key剩余秒数
获取剩余生存时间(毫秒)PTTL key剩余毫秒数
判断 Key 是否存在EXISTS key0 或 1
获取 Key 的数据类型TYPE key类型字符串
设置秒级过期时间EXPIRE key seconds0 或 1
设置绝对过期时间(秒)EXPIREAT key timestamp0 或 1
设置毫秒级过期时间PEXPIRE key ms0 或 1
设置绝对过期时间(毫秒)PEXPIREAT key timestamp0 或 1
原子设置值和过期时间戳SET key value EXAT timestampOK
移除过期时间PERSIST key0 或 1
获取服务器当前时间TIME秒 + 微秒

总结

EXPIRETIME的核心作用是返回 Key 过期时刻的 Unix 时间戳(秒),便于应用端获取绝对过期时间点:

EXPIRETIME key

使用时重点注意四点:

  • 返回值约定与TTL一致:正数表示过期时间戳,-1表示永久有效,-2表示 Key 不存在。
  • EXPIRETIME返回的是绝对时间戳,TTL返回的是剩余秒数,两者可互相换算。
  • SET(不带选项)会清除过期时间,EXPIRE/EXPIREAT会更新过期时间,PERSIST会移除过期时间,EXPIRETIME能反映这些变化。
  • EXPIRETIME从 Redis 7.0 开始支持,低版本可用TTL加当前时间戳间接计算过期时间戳。
http://www.cnnetsun.cn/news/4300144.html

相关文章:

  • 自托管数据管理器UI重构实战:从v1到v2的界面与性能优化
  • Java课程设计实战:员工工资管理系统V3完整实现
  • 腾讯校招2016编程题解析:格雷码、摩尔投票与动态规划
  • 从零搭建JARVIS语音助手:语音识别+大模型+语音合成全流程
  • B站社招面试全流程复盘:从投递到Offer的备考策略与避坑指南
  • 容器预热预跳转方案
  • 小苯的能量项链【牛客tracker 每日一题】
  • 0.3%差距背后的技术选型真相:从DeepSeek接入Claude Code看工程成本
  • 湿度传感器的类型有哪些?国产平替的优势
  • ROS2机器人自主导航与视觉系统构建实战指南
  • Rmweb:为reMarkable Paper Pro打造的软件渲染墨水屏浏览器
  • 从OpenAI自研芯片看AI芯片之争:GPU、CUDA与开发者实战
  • 【2026年】通风柜气流组织CFD仿真分析与应用
  • 水下图像增强融合算法MATLAB实现与参数调优详解
  • Python 的异常处理机制 —— 可选导入:开源包init.py优雅降级实践
  • 【AI 业务流架构师】04-Markdown调教法:铸造Agent的人格内核与价值观
  • STM32H723ZGT6与AT25SF128A:外部加载器开发与SPI Nor Flash烧录实战
  • 12岁小学生重构Python代码:一场教科书级重构实战
  • 网易运维开发笔试真题复盘:Linux、脚本、监控与CI/CD考点全解析
  • GitHub每日热评|OpenAI Codex 源码解析:一个 Rust 工具型项目是如何组织 CLI、工作流与测试的
  • 国企绩效考核破局之道:从制度设计到数字赋能的完整路径
  • Java SE 基础 · 点1 封装
  • 驱动盘清理SOP:告别仓库爆满,一套流程搞定绝区零装备管理
  • STM32C5 ADC交错采样配置实战:从原理到CubeMX与DMA调试
  • 低功耗MCU踩坑:STANDBY下SideKick协处理器GPIO误判根因与修复
  • 智能体延迟优化指南:从毫秒级推理到工具调用链路
  • SSM停车场管理系统源码解析:从框架原理到部署实战
  • 数据库工程与查询优化案例深度复盘‌
  • 工厂数字孪生平台选型指南:从车间透明化到能源可视化
  • 2013年Google笔试题精讲:从算法内核到面试实战的修炼指南