Redis(67)Redis的SETNX命令是如何工作的?

SETNX 是 Redis 提供的一个原子性命令,用于在键不存在时设置键值对。SETNX 是 "SET if Not eXists" 的缩写,主要应用于实现分布式锁等场景。下面是详细的工作原理以及如何在 Java 中使用 SETNX 命令的示例。

SETNX 命令的工作原理

  1. 检查键是否存在:Redis 首先检查给定的键是否存在。
  2. 设置键值对 :如果键不存在,Redis 将设置键值对,并返回 1
  3. 不做任何操作 :如果键已经存在,Redis 不会设置新的值,并返回 0

Java 使用 SETNX 示例

环境准备

  1. 需要 Redis 服务运行中。
  2. 需要引入 Jedis 库,这是一个 Redis 的 Java 客户端。

Maven 依赖

xml 复制代码
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.0.1</version>
</dependency>

基本使用示例

java 复制代码
import redis.clients.jedis.Jedis;

public class RedisSetNXExample {
    public static void main(String[] args) {
        // 连接到 Redis 服务器
        Jedis jedis = new Jedis("localhost", 6379);

        // 键和值
        String key = "mykey";
        String value = "Hello";

        // 使用 SETNX 命令
        Long result = jedis.setnx(key, value);

        if (result == 1) {
            System.out.println("Key was set successfully.");
        } else {
            System.out.println("Key already exists.");
        }

        // 再次尝试设置相同的键
        String newValue = "World";
        result = jedis.setnx(key, newValue);

        if (result == 1) {
            System.out.println("Key was set successfully with new value.");
        } else {
            System.out.println("Key already exists, new value was not set.");
        }

        // 关闭连接
        jedis.close();
    }
}

使用 SETNX 实现分布式锁

分布式锁是 SETNX 的一个典型应用场景。下面是一个使用 SETNX 实现分布式锁的示例:

获取锁

java 复制代码
import redis.clients.jedis.Jedis;

public class RedisDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int lockExpireTime;

    public RedisDistributedLock(Jedis jedis, String lockKey, int lockExpireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.lockExpireTime = lockExpireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        Long result = jedis.setnx(lockKey, lockValue);

        if (result == 1) {
            // 设置过期时间,防止死锁
            jedis.expire(lockKey, lockExpireTime);
            return true;
        }

        return false;
    }

    public boolean releaseLock() {
        // 使用 Lua 脚本确保原子性
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) " +
                           "else return 0 end";

        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }
}

使用示例

java 复制代码
public class TestDistributedLock {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        String lockKey = "distributed_lock";
        RedisDistributedLock lock = new RedisDistributedLock(jedis, lockKey, 10);

        if (lock.acquireLock()) {
            try {
                System.out.println("Lock acquired, performing critical operations.");
                // 执行需要同步的操作
            } finally {
                lock.releaseLock();
                System.out.println("Lock released.");
            }
        } else {
            System.out.println("Failed to acquire lock.");
        }

        jedis.close();
    }
}

总结

通过上述代码示例,我们详细介绍了 SETNX 命令的工作原理,并展示了如何在 Java 中使用 SETNX 命令以及使用 SETNX 实现分布式锁的方式。这样可以确保在分布式环境中多个进程或线程能够协调地访问共享资源。

相关推荐
65岁退休Coder几秒前
LangChain v1.3.4 笔记 - 07 补充:链式调用 LCEL
后端·python·langchain
卷无止境11 分钟前
FastAPI 部署在 Nginx 后面到底该怎么配
后端·python
码流怪侠13 分钟前
用 WiFi 信号数人头:howmanypeoplearearound 项目深度解析
后端·开源·github
心运软件39 分钟前
SpringBoot+ Vue校园社团管理平台的完整架构设计
vue.js·后端
Jodie同志1 小时前
第16~23天:持久化、HITL、流式、MCP与安全
前端·后端·agent
Jodie同志1 小时前
第1~15天:原生Agent、RAG与LangGraph基础(完整代码实操)
前端·后端·agent
Zane19941 小时前
单例线程安全、生产者消费者、死锁:并发面试三连问串讲
java·后端
用户69371750013841 小时前
#DeepSeek+Pi‑Agent 王炸组合跑赢 Claude‑Code!
前端·人工智能·后端
Zane19942 小时前
类变量与实例变量:一个共享列表引发的线上事故
后端·python
Scene2162 小时前
AgentScope 2.0:2. 快速上手 从零构建生产级智能体
后端