字段不存在才写入
HSETNX 是单字段版的「不存在才写」:字段不存在时写入并返回 1,已存在则返回 0 且不改动原值。它是单条命令,天然原子,适合初始化默认值而不覆盖用户已有设置的场景。
基本信息
| 适用 | Redis 2.0 及以上 Hash 命令 |
|---|---|
| 作用范围 | 单个字段,不是整个键 |
| 原子性 | 单命令原子,无需额外加锁 |
| 返回值 | 1 表示写入成功,0 表示字段已存在未改动 |
示例
示例
HSETNX task:88 status pending # 1:字段不存在,写入成功
HSETNX task:88 status running # 0:已存在,拒绝覆盖
HGET task:88 status # pending:原值保持不变
HSETNX config:site theme light # 初始化默认配置,不覆盖已设置项
HGETALL config:site # 查看当前全部字段
HSTRLEN config:site theme # 字段值的字节长度返回值与语义
| 返回值 | 含义 | 业务处理 |
|---|---|---|
| 1 | 字段原先不存在,已写入 | 按新值初始化处理 |
| 0 | 字段已存在,未改动 | 属于正常语义,不要当异常重试 |
| 键不存在时 | 相当于新建 Hash 并写入 | 返回 1 |
| 多字段初始化 | 逐字段调用或改用 Lua | 注意多次调用之间的并发窗口 |
典型使用场景
- 初始化默认配置,保留用户已设置的项
- 任务状态幂等初始化:只在首次设置状态
- 灰度标记写入:不覆盖已有的分组标记
- 补齐缺失字段,避免影响已存在的数据
- 配合 HGETALL 做配置合并前的准备动作
需要整键级别的「不存在才写」时用 SET 的 NX 选项;需要多字段一起判断时,用 Lua 把判断与写入合成一次原子操作。
不要用 HSETNX 实现跨进程互斥:不同进程写不同字段都可能返回 1,互斥必须用 SET NX 加过期时间或专门的锁方案。
与相关命令的分工
- 整键级不存在才写用 SET 的 NX 选项,而不是 HSETNX
- 字段存在也要覆盖时用 HSET,语义更直接
- 多字段一起判断再写入时用 Lua 脚本保证原子性
- 判断字段是否存在用 HEXISTS,写入用 HSETNX,两者职责不同
幂等初始化的写法
- 用 HSETNX 逐字段初始化默认值,用户已设置的项不会被覆盖
- 需要整批默认值时,可在应用层先读一次再决定写哪些字段
- 初始化脚本重复执行也不会产生副作用,适合放在部署流程里