Redis HGETEX 命令详细教程
HGETEX读取 Hash 中一个或多个字段的值,并可在同一条命令中设置或清除这些字段的过期时间。它从 Redis 8.0.0 起提供,是“读取加续期”的原子组合。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、概览与语法
HGETEX key [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | PERSIST] FIELDS numfields field [field ...]| 项目 | 说明 |
|---|---|
| 数据类型 | Hash |
| 支持版本 | Redis 8.0.0 起 |
| key | 一个 Hash Key |
| 过期选项 | EX、PX、EXAT、PXAT、PERSIST 五者最多选一,也可以完全不写 |
| FIELDS | 必填关键字,不可省略 |
| numfields | 字段数量,必须与后续字段参数个数一致 |
| 返回值 | 值数组,顺序与输入字段一致;缺失字段对应空值 |
| 时间复杂度 | O(N),N 为指定字段数量 |
| ACL | @write、@hash、@fast |
| 命令标记 | write |
不写任何过期选项时,HGETEX 的行为接近按指定字段读取,不修改任何 TTL。命令会修改字段的过期时间,因此被标记为写命令,不能用在只读副本或只读连接上。$TRAE_REF
二、过期选项语义
五个选项互斥,不能组合使用。
| 选项 | 含义 |
|---|---|
| EX seconds | 从现在起经过指定秒数后到期 |
| PX milliseconds | 从现在起经过指定毫秒数后到期 |
| EXAT unix-time-seconds | 在指定 Unix 秒级时间戳到期 |
| PXAT unix-time-milliseconds | 在指定 Unix 毫秒级时间戳到期 |
| PERSIST | 移除字段已有的过期时间,使其变为永久字段 |
| 不写 | 保持字段现有 TTL 不变 |
EXAT 与 PXAT 的时间戳若已过去,字段会立即被删除;此时返回值仍然包含被删除前的值,因为读取发生在删除之前。
三、基础示例
以下命令需要 Redis 8.0 或更新版本,在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。
DEL tutorial:{hgetex}:session HSET tutorial:{hgetex}:session token abc user u100 theme dark HGETEX tutorial:{hgetex}:session EX 120 FIELDS 1 token HGETEX tutorial:{hgetex}:session EX 100 FIELDS 1 user HTTL tutorial:{hgetex}:session FIELDS 3 token user theme HGETEX tutorial:{hgetex}:session FIELDS 2 theme absent HGETEX tutorial:{hgetex}:session PERSIST FIELDS 1 token HTTL tutorial:{hgetex}:session FIELDS 1 token预期结果:前两次 HGETEX 分别返回["abc"]与["u100"];HTTL 返回形如[91, 85, -1]的数组,token 与 user 是递减的剩余秒数,theme 为 -1 表示没有 TTL;不带选项的 HGETEX 返回["dark", nil],即 theme 的值与 absent 的空值,且不改变任何 TTL;PERSIST 后 token 的 HTTL 变为 -1。
示例中的秒数会随执行时刻变化,因此只描述形态,不给出固定数字。
四、不创建字段与空值处理
HGETEX 是读取语义,不会创建不存在的 Key 或字段,也不会为缺失字段设置过期时间。缺失字段在返回值中占据一个位置,内容为空值,长度始终等于请求的字段数量。
| 场景 | 行为 |
|---|---|
| Key 不存在 | 按输入字段数返回多个空值,不创建 Key,不设置任何 TTL |
| 字段不存在 | 该项返回空值,该字段不会被创建,也不会产生 TTL |
| 字段值为空字符串 | 返回空字符串,字段存在,可按选项设置 TTL |
| Key 是 String、List 等非 Hash | 报 WRONGTYPE 错误 |
| 选项写多个或未知选项 | 报语法错误 |
| numfields 与实际字段数不符 | 报语法错误 |
只关心存在字段的续期时,应先用 HEXISTS 过滤,或接受缺失字段返回空值的事实。
五、与相近命令的区别
| 命令 | 读取 | 修改 TTL | 删除 | 起始版本 |
|---|---|---|---|---|
| HGET | 单字段 | 否 | 否 | 2.0 |
| HMGET | 多字段 | 否 | 否 | 2.0 |
| HEXPIRE | 否 | 是(相对秒) | 否 | 7.4 |
| HPERSIST | 否 | 清除 | 否 | 7.4 |
| HGETEX | 多字段 | 是 | 否 | 8.0 |
| HGETDEL | 多字段 | 否 | 是 | 8.0 |
| GETEX | 单 Key(String) | 是 | 否 | 6.2 |
HGETEX 可以看作 Hash 版本的 GETEX,它把“取值”和“续期”合并,避免先 HGET 再 HEXPIRE 的两次往返与竞态窗口。如果只是单纯读值、不需要改 TTL,用 HMGET 更直观,也不必让只读实例承担写命令。
六、典型场景:缓存命中续期
滑动过期缓存是 HGETEX 最典型的使用方式:命中时读取值并把 TTL 重置为完整周期,未命中时由业务回源并重新写入。
处理一次请求: 1. HGETEX cache:{user}:profile EX 600 FIELDS 3 name level avatar 2. 若返回的值中包含空值,说明对应字段缺失或已过期,需要回源 3. 回源后使用 HSET 写入,并配合 HEXPIRE 设置字段 TTL注意续期与回源不是同一个原子操作:HGETEX 只保证“读取加续期”这一步原子,回源与写回仍在命令之外,多个并发请求可能同时回源。高并发场景可配合互斥锁或允许短暂重复回源。另外,给字段设置 TTL 意味着字段会独立消失,业务需要能容忍字段级的缺失,而不是只依赖整个 Key 的过期。
七、并发、原子性与重试
HGETEX 对多个字段是原子执行的,返回值来自执行瞬间的一致快照,不会读到“改了一半”的 TTL 状态。但“先 HGETEX 判断再写入”仍是跨命令流程,其他客户端可能在两次调用之间修改数据。
使用相对时间选项(EX、PX)时,重试会从新的时刻重新计时,可能无意延长有效期;需要固定截止时间时应使用 EXAT 或 PXAT。请求超时也不代表未执行,重发前可先用 HEXPIRETIME 或 HTTL 检查字段当前状态。
单条命令会一次性修改多个字段的 TTL,字段数量多时注意控制批次大小,避免单次请求过大。
八、Python 客户端示例
前提为已安装 redis-py 且服务端为 Redis 8.0 或更新版本。使用通用接口显式展示 FIELDS 语法。
importredis r=redis.Redis(host="localhost",port=6379,decode_responses=True)k="tutorial:{hgetex}:python"try:r.delete(k)r.hset(k,mapping={"token":"abc","user":"u100","theme":"dark"})print(r.execute_command("HGETEX",k,"EX",120,"FIELDS",1,"token"))# ['abc']fields=["token","theme","absent"]values=r.execute_command("HGETEX",k,"FIELDS",len(fields),*fields)print(values)# ['abc', 'dark', None]print(r.execute_command("HTTL",k,"FIELDS",3,*fields))# [约120, -1, -2]print(r.execute_command("HGETEX",k,"PERSIST","FIELDS",1,"token"))# ['abc']print(r.execute_command("HTTL",k,"FIELDS",1,"token"))# [-1]finally:r.delete(k)r.close()九、练习、排错与总结
练习:新建tutorial:{hgetex}:exercise,写入 a=1、b=2;执行HGETEX ... EX 300 FIELDS 2 a b,预期返回"1"、"2";用 HTTL 确认两个字段都有正数剩余时间;再执行HGETEX ... PERSIST FIELDS 1 a,预期 HTTL 对 a 返回 -1;最后执行HGETEX ... EXAT 1 FIELDS 1 b,预期返回"2"但 b 随即被删除,HEXISTS 为 0。
排错要点:unknown command 时确认服务端版本不低于 8.0;报错时检查是否同时写了两个过期选项;返回空值说明字段不存在或已过期,可用 HEXISTS 与 HTTL 区分;HTTL 返回 -1 表示字段永久有效,-2 表示字段不存在;写入后 TTL 意外消失,检查是否随后用 HSET 覆盖了该字段。清理使用DEL tutorial:{hgetex}:session tutorial:{hgetex}:exercise。速记:8.0 起支持、读取同时可选续期、五个过期选项互斥、不创建缺失字段、相对时间重试会重新计时。