Redis HPEXPIRE 命令详细教程
HPEXPIRE 为 Hash 中一个或多个字段设置以毫秒为单位的相对过期时间。它与 HEXPIRE 语义完全相同,区别只在时间精度。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、概览与语法
redis
HPEXPIRE key milliseconds [NX | XX | GT | LT] FIELDS numfields field [field ...]
| 项目 | 说明 |
|---|---|
| 数据类型 | Hash 的字段级过期时间 |
| 支持版本 | Redis 7.4.0 起 |
| key | 一个 Hash Key |
| milliseconds | 整数毫秒数,相对于本次命令执行时刻 |
| 条件选项 | NX、XX、GT、LT 四者最多选一,互斥 |
| FIELDS | 必填关键字 |
| numfields | 字段数量,必须与后续字段参数个数一致 |
| 时间复杂度 | O(N),N 为指定字段数量 |
| ACL | @write、@hash、@fast |
| 命令标记 | write、denyoom、fast |
官方描述直接指出:本命令与 HEXPIRE 工作方式相同,只是过期时间以毫秒而非秒指定。$TRAE_REF
二、逐字段返回值
返回数组,元素顺序与输入字段顺序一致。
| 数值 | 含义 |
|---|---|
| -2 | 该字段不存在,或整个 Key 不存在 |
| 0 | 指定的 NX、XX、GT、LT 条件未满足 |
| 1 | 过期时间已设置或更新 |
| 2 | 以 0 毫秒调用时,字段被立即删除 |
官方说明中,2 的触发条件是:以 0 秒或 0 毫秒调用 HEXPIRE 或 HPEXPIRE,或者以过去的 Unix 时间调用 HEXPIREAT 或 HPEXPIREAT。错误情形包括参数解析失败、缺少必需参数、出现未知参数、参数类型或范围不合法,以及 Key 存在但不是 Hash。$TRAE_REF
三、基础示例
以下命令需要 Redis 7.4 或更新版本,在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。
redis
DEL tutorial:{hpexpire}:profile
HSET tutorial:{hpexpire}:profile name Alice temp draft
HPEXPIRE tutorial:{hpexpire}:profile 2000 FIELDS 2 temp name
HPTTL tutorial:{hpexpire}:profile FIELDS 2 temp name
HPEXPIRE tutorial:{hpexpire}:profile 2000 FIELDS 2 temp absent
预期结果:HPEXPIRE 返回 [1, 1];HPTTL 返回两个接近 2000 的毫秒值;最后一次返回 [1, -2],absent 因不存在为 -2。手动等待超过 2 秒后再执行 HGETALL tutorial:{hpexpire}:profile 会得到空数组,因为两个字段都到期,整个 Key 随之消失。
四、与 HEXPIRE 及绝对时间版本的对照
| 命令 | 时间表达 | 单位 | 起始版本 |
|---|---|---|---|
| HEXPIRE | 相对 | 秒 | 7.4 |
| HPEXPIRE | 相对 | 毫秒 | 7.4 |
| HEXPIREAT | 绝对 | 秒级时间戳 | 7.4 |
| HPEXPIREAT | 绝对 | 毫秒级时间戳 | 7.4 |
相对时间适合"从现在起多少时间后过期"的场景,例如缓存 2 秒内有效、验证码 5 分钟有效。绝对时间适合"在某个固定时刻过期"的场景,例如活动在指定时间点结束。相对时间在重试时会重新计时,绝对时间不会,这一点在设计幂等接口时很重要。
毫秒精度并不意味着毫秒级精确定时。Redis 的过期清理是惰性与定期相结合的,字段到期与实际不可见之间可能存在很短但非零的延迟,不要依赖它做精确调度。
五、条件选项 NX、XX、GT、LT
四个选项互斥,对每个字段独立判断。
| 选项 | 判断条件 |
|---|---|
| NX | 字段当前没有过期时间时才设置 |
| XX | 字段当前已有过期时间时才设置 |
| GT | 新过期时间严格晚于当前过期时间时才设置 |
| LT | 新过期时间严格早于当前过期时间时才设置 |
官方特别说明:对于 GT 与 LT 而言,没有过期时间的字段(non-volatile)被视为无限大的 TTL。因此有限时间的 GT 对无 TTL 字段通常不成立,而 LT 会成立。$TRAE_REF
redis
DEL tutorial:{hpexpire}:cond
HSET tutorial:{hpexpire}:cond a A b B
HPEXPIRE tutorial:{hpexpire}:cond 1000 XX FIELDS 1 a
HPEXPIRE tutorial:{hpexpire}:cond 1000 NX FIELDS 1 a
HPEXPIRE tutorial:{hpexpire}:cond 5000 GT FIELDS 2 a b
HPEXPIRE tutorial:{hpexpire}:cond 100 LT FIELDS 2 a b
在无并发修改的前提下,四次调用依次返回 [0]、[1]、[1, 0]、[1, 1]。GT 对已有 1000 毫秒期限的 a 成立;b 无 TTL 被视为无限远,GT 不成立而 LT 成立。同一调用可能部分字段成功、部分失败。
六、边界情况与错误处理
| 场景 | 行为 |
|---|---|
| Key 不存在 | 按输入字段数返回多个 -2,不创建 Key |
| 字段不存在 | 该项返回 -2 |
| milliseconds 为 0 | 该字段被立即删除,返回 2 |
| milliseconds 为负数 | 报参数范围错误 |
| milliseconds 不是整数 | 报参数类型错误 |
| Key 是 String、List 等非 Hash | 报 WRONGTYPE 错误 |
| numfields 与实际字段数不符 | 报语法错误 |
需要注意,HPEXPIRE 只作用于已存在的字段,不会创建字段。若希望写入值的同时设置 TTL,应使用 HSETEX(Redis 8.0 起)。
七、客户端示例
前提为已安装 redis-py 且服务端为 Redis 7.4 或更新版本。使用通用接口显式展示 FIELDS 语法。
python
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
k = "tutorial:{hpexpire}:python"
try:
r.delete(k)
r.hset(k, mapping={"a": "A", "b": "B"})
fields = ["a", "b", "missing"]
result = r.execute_command("HPEXPIRE", k, 2000, "FIELDS", len(fields), *fields)
print(result) # [1, 1, -2]
print(r.execute_command("HPTTL", k, "FIELDS", 2, "a", "b")) # 约 [2000, 2000]
print(r.execute_command("HPEXPIRE", k, 0, "FIELDS", 1, "a")) # [2],立即删除
print(r.hexists(k, "a")) # False
finally:
r.delete(k)
r.close()
八、并发、重试与适用场景
单条 HPEXPIRE 对多个字段原子执行,但"先 HSET 写值,再 HPEXPIRE 设期限"是两条独立调用,中间可能有其他写入或客户端中断。需要一起生效时应使用事务或脚本,并检查所有回复。
相对 TTL 的无条件重试会从重试时刻重新计时,可能无意延长有效期。若业务要求固定截止时间,应改用 HPEXPIREAT。请求超时也不代表未执行,重发前可先用 HPTTL 或 HPEXPIRETIME 检查字段当前状态。
典型场景:需要亚秒级精度的短缓存字段、限流窗口、短时令牌。控制每批字段数量与 Hash 规模,不要把过期机制当作精确任务调度器。
九、练习、排错与总结
练习:新建 tutorial:{hpexpire}:exercise,写入 a=1、b=2;执行 HPEXPIRE ... 1500 FIELDS 2 a b,预期返回 [1, 1];用 HPTTL 确认两个字段都有接近 1500 的毫秒值;等待超过 1.5 秒后执行 HLEN,预期返回 0,因为两个字段都已到期、Key 随之消失。
排错要点:unknown command 时确认服务端版本不低于 7.4;返回 0 检查条件选项;返回 -2 检查字段是否缺失或已到期;返回 2 说明传入了 0 或已过去的时间;HPTTL 返回 -1 表示字段永久有效而非命令失败。清理使用 DEL tutorial:{hpexpire}:profile tutorial:{hpexpire}:cond tutorial:{hpexpire}:exercise。速记:7.4 起支持、毫秒相对时间、FIELDS 必填、返回 -2/0/1/2、0 毫秒立即删除、不创建字段。