SETNX 是什么
SETNX 是 SET if Not eXists 的缩写:仅当键不存在时写入,成功返回 1,键已存在返回 0 且不改动原值。它自身没有过期参数,所以锁与去重场景更推荐等价的 SET key value NX EX 秒(或 NX PX 毫秒),把判断存在、写入、设过期压成一条原子命令,中间不会被打断。
基本信息
| 适用版本 | Redis 2.6+;SET 支持 NX/EX 需 2.6.12 及以上 |
|---|---|
| 语法 | SETNX key value |
| 返回值 | 1=写入成功;0=键已存在,未做修改 |
| 等价写法 | SET key value NX |
| 带过期写法 | SET key value NX EX 3600 / NX PX 5000 |
典型使用场景
- 任务幂等去重:同一订单号只允许处理一次,写入成功的一方才继续
- 获取分布式锁:NX 成功即持锁,配合 PX 过期防止持锁进程崩溃后死锁
- 缓存预热互斥:并发请求里只放一个去回源加载,其余等待或返回旧值
- 领券、抢购类防重复:以用户加活动维度做一次性标记
- 定时任务防重叠:到点先抢占标记,避免上一轮没跑完就再起一个
两种写法对比
两种写法对比
SETNX job:sync:20261012 1 # 成功返回 1;已存在返回 0,键不变
EXPIRE job:sync:20261012 3600 # 必须补过期,且与上一条不是原子操作
TTL job:sync:20261012 # 确认过期时间是否真的设上了
SET job:sync:20261012b 1 NX EX 3600 # 一条命令搞定,推荐写法
SET lock:order:42 6f1d2c4e NX PX 5000 # 锁场景用毫秒级,秒级精度过粗
GET lock:order:42 # 记下写入的 token,释放时要比对返回值读法
| 返回值 | 含义 | 调用方动作 |
|---|---|---|
| 1 | 键此前不存在,本次写成功 | 视为抢到锁或首次执行,继续业务逻辑 |
| 0 | 键已存在,未做任何修改 | 区分他人持锁与重复任务,选择等待或直接返回 |
| nil | 键不存在时的 GET 类返回 | 确认命令拼写与连接是否指向正确实例 |
SETNX + EXPIRE 之间存在崩溃窗口:拿到键还没设过期就挂掉,键会永久残留(经典死锁成因);用 SET ... NX EX 单条原子命令规避。
SETNX 的语义是不存在才写,键已存在时不会刷新过期时间。续期必须显式调用 EXPIRE,或使用带看门狗的客户端库,不要指望再次 SETNX 能成功。