news 2026/10/7 2:44:30

Redis命令:HSETNX

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis命令:HSETNX

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)
ACL@write、@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 返回"Hello";HLEN 返回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整个 Key(String 类型)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 返回0,HGET 仍为"1",HTTL 仍为正数,说明值和 TTL 都未被改动;对不存在的 b 返回1,b 的 HTTL 为-1,即新字段默认永久有效。字段级 TTL 需要 Redis 7.4 或更高版本。

六、边界情况与错误处理

场景行为
Key 不存在创建 Hash,写入字段,返回 1
字段已存在返回 0,不修改值与 TTL
Key 是 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 r=redis.Redis(host="localhost",port=6379,decode_responses=True)k="tutorial:{hsetnx}:python"try: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()

Java(Jedis)示例,返回 long:

try(Jedisjedis=newJedis("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或使用 HSETEX(8.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、新字段默认永久。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 2:44:04

从原理到实测:一文搞懂PMIC电源管理芯片(LDO/Buck)选型与布局

这周帮朋友看一块控制板,现象很奇怪:明明各路电源都量得到电压,系统就是偶发重启。用示波器一抓,发现FPGA核心电压掉到0.7V以下还带着毛刺,问题直指板上一颗不起眼的电源管理芯片PMIC。老实说,很多电源问题…

作者头像 李华
网站建设 2026/10/7 2:43:16

从零搭建灌装监控系统(十四):Serilog四路日志输出

Serilog 四路日志输出这是「从零搭建灌装监控系统」系列第14篇。报警系统需要日志,设备通信需要日志,配置保存也需要日志。真正让人头疼的不是写一条日志,而是同一条日志如何同时服务现场操作员、开发调试、历史查询和问题定位。这篇用 Seril…

作者头像 李华
网站建设 2026/10/7 2:43:15

源站连接超时诊断方法(进阶篇)最佳实践与踩坑记录

本文深入探讨源站连接超时诊断方法(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。很多团队在故障排查实战场景中都会遇到与源站连接超时诊断方法(进阶篇)相关的挑战。本文结合生产环境经…

作者头像 李华
网站建设 2026/10/7 2:43:13

AI赋能企业数据资产:从盘点、血缘到平台架构的落地拆解

简介:这份PPT方案面向金融、制造、零售等行业中负责数字化转型的决策者与数据平台规划人员,系统梳理了AI赋能企业数据资产管理与数据平台建设的完整路径。内容从建设背景与需求分析切入,覆盖总体架构设计、数据资产治理体系、AI能力平台建设、…

作者头像 李华
网站建设 2026/10/7 2:41:38

C++17 核心新特性总览:一张速查表 + 8 个上手示例

C17 不是「又多了一堆语法糖」的版本,它是让日常业务代码真正变短、变安全的一版:std::optional 替掉了 -1 这种哨兵值,if (auto it m.find(k); it ! m.end()) 把迭代器关进了作用域,std::filesystem 让路径操作不再写平台相关的…

作者头像 李华