Redis HSETNX 命令详细教程HSETNX仅在字段不存在时设置其值字段已存在则不做任何操作。它返回 0 或 1是字段级的“不存在才写入”原语。资料合集https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338一、概览与语法HSETNX key field value项目说明数据类型Hash支持版本Redis 2.0.0 起keyHash 的 Key不存在时自动创建field字段名仅在其不存在时设置value要写入的值返回值1 表示字段是新的且已设置0 表示字段已存在且未做操作时间复杂度O(1)ACLwrite、hash、fast命令标记write、denyoom、fast官方说明如果 Key 不存在会创建一个持有 Hash 的新 Key如果字段已存在该操作不产生任何效果。$TRAE_REF二、基础示例以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明未实际连接 Redis 运行。示例沿用官方示例。DEL tutorial:{hsetnx}:myhash HSETNX tutorial:{hsetnx}:myhash field Hello HSETNX tutorial:{hsetnx}:myhash field World HGET tutorial:{hsetnx}:myhash field HLEN tutorial:{hsetnx}:myhash预期结果第一次 HSETNX 返回1并创建 Key第二次针对同一字段返回0值未被覆盖HGET 返回HelloHLEN 返回1。这组示例完整体现了 HSETNX 的核心语义第二次写入被静默忽略不报错。三、返回值语义与存在性判定场景返回值字段不存在含 Key 不存在1写入成功字段已存在0未做任何修改判断“字段是否存在”的标准是字段名本身与字段值无关字段当前状态HSETNX 结果字段不存在返回 1写入字段值为空字符串返回 0不写入字段值为0返回 0不写入字段值为null返回 0不写入字段已到期7.4 及以上视同不存在返回 1因此“值为空”或“值为假”都不等于“字段不存在”。如果业务把空值当作未设置需要在应用层额外约定而不能依赖 HSETNX 的判断。四、与 HSET、SET NX 的区别命令判断粒度返回值说明HSETNX单个字段0 或 1字段不存在才写入HSET无判断新增字段数无条件覆盖SET NX整个 KeyString 类型OK 或空值Key 不存在才设置HSETEX FNX字段集合8.0 起0 或 1所有字段都不存在才写入HSETNX 一次只能处理一个字段没有批量版本。需要多个字段都“不存在才写入”时应使用 HSETEX 的 FNX 选项Redis 8.0 起或在脚本中组合判断。另外注意返回值形态不同SET NX 成功返回OK、失败返回空值而 HSETNX 返回整数 1 或 0不能混用判断逻辑。五、TTL 与覆盖语义HSETNX 只在字段不存在时写入因此它不会覆盖已有字段也就不会清除已有字段的 TTL。新建的字段默认不带过期时间。DEL tutorial:{hsetnx}:ttl HSET tutorial:{hsetnx}:ttl a 1 HEXPIRE tutorial:{hsetnx}:ttl 300 FIELDS 1 a HTTL tutorial:{hsetnx}:ttl FIELDS 1 a HSETNX tutorial:{hsetnx}:ttl a 999 HGET tutorial:{hsetnx}:ttl a HTTL tutorial:{hsetnx}:ttl FIELDS 1 a HSETNX tutorial:{hsetnx}:ttl b 2 HTTL tutorial:{hsetnx}:ttl FIELDS 1 b预期结果设置 TTL 后 HTTL 返回正数HSETNX 对已存在的 a 返回0HGET 仍为1HTTL 仍为正数说明值和 TTL 都未被改动对不存在的 b 返回1b 的 HTTL 为-1即新字段默认永久有效。字段级 TTL 需要 Redis 7.4 或更高版本。六、边界情况与错误处理场景行为Key 不存在创建 Hash写入字段返回 1字段已存在返回 0不修改值与 TTLKey 是 String、List 等非 Hash报 WRONGTYPE 错误参数个数不足或多余报语法错误HSETNX 只接受 key、field、value字段名或值为空字符串合法正常处理内存达到上限且策略禁止写入命令带 denyoom 标记写入被拒绝HSETNX 无法对已存在字段做条件更新。需要“值等于某条件时才更新”时应使用 Lua 脚本或带 WATCH 的事务。七、原子性与并发价值HSETNX 的真正价值在于原子性。用“先 HEXISTS 判断、再 HSET 写入”实现同样逻辑时两次调用之间存在窗口期其他客户端可能已抢先写入导致后写者覆盖先写者的数据。非原子写法存在竞态 客户端 A: HEXISTS h f - 0 客户端 B: HEXISTS h f - 0 客户端 A: HSET h f A 客户端 B: HSET h f B B 覆盖了 A 的写入 原子写法 客户端 A: HSETNX h f A - 1 客户端 B: HSETNX h f B - 0 B 未写入A 的值被保留因此 HSETNX 适合初始化默认值、抢占式分配唯一标识、保证某字段只被设置一次等场景。八、客户端示例前提为已安装 redis-py 并准备好本地测试实例。importredis rredis.Redis(hostlocalhost,port6379,decode_responsesTrue)ktutorial:{hsetnx}:pythontry:r.delete(k)print(r.hsetnx(k,field,Hello))# True字段不存在写入成功print(r.hsetnx(k,field,World))# False字段已存在未写入print(r.hget(k,field))# Hello# 值为空字符串也算“已存在”r.hset(k,empty,)print(r.hsetnx(k,empty,x))# Falsefinally:r.delete(k)r.close()JavaJedis示例返回 longtry(JedisjedisnewJedis(localhost,6379)){System.out.println(jedis.hsetnx(tutorial:{hsetnx}:java,field,Hello));// 1System.out.println(jedis.hsetnx(tutorial:{hsetnx}:java,field,World));// 0System.out.println(jedis.hget(tutorial:{hsetnx}:java,field));// Hellojedis.del(tutorial:{hsetnx}:java);}九、典型场景与使用建议典型用途初始化配置项的默认值、保证某字段只被写入一次例如首次登录时间、抢占式领取标识、幂等写入。使用建议建议说明用返回值判断是否写入成功1 表示写入0 表示已被占用不要用空值表达“未设置”空字符串也算已存在需要批量时改用 HSETEX FNXHSETNX 只支持单字段需要设置 TTL 时配合 HEXPIRE或使用 HSETEX8.0 起需要条件更新已有值使用 Lua 脚本或 WATCH 事务HSETNX 写入的新字段不带过期时间。若业务要求“首次写入并自动过期”需要额外调用 HEXPIRE或用 HSETEX 一条命令完成。十、练习、排错与总结练习新建tutorial:{hsetnx}:exercise执行HSETNX ... a 1预期返回1再次执行HSETNX ... a 2预期返回0且 HGET 仍为1用HSET ... empty 写入空字符串后执行HSETNX ... empty x预期返回0理解“空值也算已存在”最后用 HTTL 确认 a 无 TTL。排错要点返回 0 不是错误表示字段已存在返回值是整数 1/0 而不是OK不要与 SET NX 的判断逻辑混用报 WRONGTYPE 时用 TYPE 检查类型报参数错误时确认只传了 key、field、value 三个参数需要批量“不存在才写入”时应改用 HSETEX 的 FNX。清理使用DEL tutorial:{hsetnx}:myhash tutorial:{hsetnx}:ttl tutorial:{hsetnx}:exercise。速记2.0 起支持、单字段原子条件写入、返回 1/0、不覆盖已有字段、不改变已有 TTL、新字段默认永久。 SEO 优化官网定制响应式建站教育培训建站