
Redis HSETEX 命令详细教程HSETEX在设置 Hash 字段值的同时可选择性地为这些字段设置过期时间。它从 Redis 8.0.0 起提供把“写入”和“设置字段 TTL”合并为一条原子命令。资料合集https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338一、概览与语法HSETEX key [FNX | FXX] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL] FIELDS numfields field value [field value ...]项目说明数据类型Hash支持版本Redis 8.0.0 起keyHash 的 Key条件选项FNX 或 FXX两者互斥过期选项EX、PX、EXAT、PXAT、KEEPTTL五者互斥FIELDS必填关键字不可省略numfields字段数量必须与后续字段值对个数一致返回值整数0 表示未设置任何字段1 表示全部字段已设置时间复杂度O(N)N 为设置的字段数量ACLwrite、hash、fast命令标记write、denyoom、fast官方说明指出如果 Key 已持有值会被覆盖且与 Key 关联的先前 TTL 会被丢弃。$TRAE_REF二、条件选项 FNX 与 FXX选项含义FNX仅当这些字段都尚不存在时才设置FXX仅当这些字段都已存在时才设置不写无条件写入覆盖已有值两者互斥不能同时使用。注意判断单位是“字段集合”而非单个字段FNX 要求所有指定字段都不存在FXX 要求所有指定字段都已存在。这与 HSETNX 只针对单个字段不同。三、过期选项五个过期选项互斥不能组合否则报错。选项含义EX seconds从当前起经过指定秒数后到期PX milliseconds从当前起经过指定毫秒后到期EXAT unix-time-seconds在指定 Unix 秒级时间戳到期PXAT unix-time-milliseconds在指定 Unix 毫秒级时间戳到期KEEPTTL保留字段已有的 TTL不改变不写按默认行为处理写入会清除原 TTL官方示例中演示了组合冲突的错误同时写EX 60 KEEPTTL会返回错误ERR Only one of EX, PX, EXAT, PXAT or KEEPTTL arguments can be specified。$TRAE_REF四、基础示例以下命令需要 Redis 8.0 或更新版本在测试实例的 redis-cli 中执行。文中结果是预期说明未实际连接 Redis 运行。示例沿用官方示例的结构。DEL tutorial:{hsetex}:mykey HSETEX tutorial:{hsetex}:mykey EXAT 1740470400 FIELDS 2 field1 Hello field2 World HTTL tutorial:{hsetex}:mykey FIELDS 2 field1 field2 HSETEX tutorial:{hsetex}:mykey FNX EX 60 FIELDS 2 field1 Hello field2 World HSETEX tutorial:{hsetex}:mykey FXX EX 60 KEEPTTL FIELDS 2 field1 hello field2 world HSETEX tutorial:{hsetex}:mykey FXX KEEPTTL FIELDS 2 field1 hello field2 world HTTL tutorial:{hsetex}:mykey FIELDS 2 field1 field2预期结果第一条 HSETEX 返回1两个字段被写入并带有指定的绝对到期时间HTTL 返回两个相同的剩余秒数。第二次调用使用 FNX但字段已存在返回0未做任何修改。第三次同时指定 EX 与 KEEPTTL报参数冲突错误。第四次仅用 KEEPTTL返回1写入新值并保留原 TTLHTTL 仍返回正数。如果示例中的绝对时间戳已经过去第一次调用会导致字段立即删除HTTL 返回 -2。实际使用时请替换为未来的时间戳。五、返回值语义返回值只有两种信息量有限返回值含义1所有字段都被设置0没有任何字段被设置条件不满足它不告诉你新增了几个字段这与 HSET 不同也不区分“部分字段因条件失败”。因为 FNX/FXX 的判断单位是整个字段集合要么全部设置要么全部不设置。需要知道新增字段数量时应使用 HSET。六、边界情况与错误处理场景行为Key 不存在且未写 FXX创建 Hash 并写入字段Key 不存在且写了 FXX条件不满足返回 0不创建 Key字段部分存在、使用 FNX条件不满足返回 0不写入任何字段字段部分缺失、使用 FXX条件不满足返回 0不写入任何字段同时指定两个过期选项报参数冲突错误EXAT/PXAT 传入过去的时间字段被写入后立即到期删除numfields 与实际字段值对不符报语法错误Key 是 String、List 等非 Hash报 WRONGTYPE 错误注意 FNX 与 SET 的 NX 语义不同SET NX 针对整个 KeyHSETEX FNX 针对字段集合。不要把两者混为一谈。七、Python 客户端示例前提为已安装 redis-py 且服务端为 Redis 8.0 或更新版本。使用通用接口显式展示 FIELDS 语法避免依赖客户端是否提供专用方法。importtimeimportredis rredis.Redis(hostlocalhost,port6379,decode_responsesTrue)ktutorial:{hsetex}:pythontry:r.delete(k)# 写入两个字段并设置 300 秒 TTLprint(r.execute_command(HSETEX,k,EX,300,FIELDS,2,a,A,b,B))# 1print(r.execute_command(HTTL,k,FIELDS,2,a,b))# 约 [300, 300]# FNX字段已存在条件不满足print(r.execute_command(HSETEX,k,FNX,EX,60,FIELDS,2,a,X,b,Y))# 0# FXX KEEPTTL字段都存在写入新值并保留 TTLprint(r.execute_command(HSETEX,k,FXX,KEEPTTL,FIELDS,2,a,X,b,Y))# 1print(r.hgetall(k))# {a: X, b: Y}print(r.execute_command(HTTL,k,FIELDS,2,a,b))# 仍为正数finally:r.delete(k)r.close()八、与相近命令的区别命令设置值设置字段 TTL条件起始版本HSET是否且清除原 TTL无2.0HSETNX是否单字段不存在2.0HSETEX是是FNX / FXX8.0HEXPIRE否是NX / XX / GT / LT7.4HGETEX否读取是无8.0HSETEX 填补了“写入并设置字段 TTL”这一步的原子性缺口。在 Redis 8.0 之前实现同样效果需要 HSET 加 HEXPIRE 两条命令中间存在竞态窗口。九、并发、原子性与典型场景HSETEX 的核心价值在于把写入与设置字段 TTL 合并为一条原子命令。用 HSET 加 HEXPIRE 两条命令实现时中间会有窗口期其他客户端可能在此期间读取到“值已更新但没有 TTL”的中间状态或者你设置的 TTL 被并发写入清除。典型场景写入带时效的会话字段、设置短时验证码、缓存字段并同时设定过期、需要条件写入字段都不存在才写的初始化逻辑。使用相对时间选项EX、PX时重试会从新的时刻重新计时可能无意延长有效期需要固定截止时间时应使用 EXAT 或 PXAT。请求超时也不代表未执行重发前可先用 HTTL 或 HGETALL 检查字段当前状态。十、练习、排错与总结练习新建tutorial:{hsetex}:exercise用HSETEX ... EX 300 FIELDS 2 a 1 b 2写入两个字段确认返回1用 HTTL 确认两个字段都有正数 TTL再用FNX EX 60 FIELDS 2 a 9 b 9调用确认返回0且值未被修改最后用FXX KEEPTTL FIELDS 2 a 9 b 9调用确认返回1、值已更新且 TTL 保留。排错要点unknown command 时确认服务端版本不低于 8.0返回 0 检查 FNX/FXX 条件是否满足注意判断单位是整个字段集合报参数冲突时检查是否同时写了两个过期选项报语法错误时检查 FIELDS 关键字与 numfields 数值写入后 TTL 意外消失说明使用了不带 KEEPTTL 的默认写入字段被立即删除说明 EXAT/PXAT 传入了过去的时间。清理使用DEL tutorial:{hsetex}:mykey tutorial:{hsetex}:exercise。速记8.0 起支持、写入与设置字段 TTL 原子完成、FNX/FXX 针对字段集合、五个过期选项互斥、返回 0 或 1、KEEPTTL 保留原 TTL。