Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。
语法
redis Setnx 命令基本语法如下:
redis 127.0.0.1:6379> SETNX KEY_NAME VALUE
可用版本
>= 1.0.0
返回值
设置成功,返回 1 。 设置失败,返回 0 。
实例
redis> EXISTS job # job 不存在 (integer) 0 redis> SETNX job "programmer" # job 设置成功 (integer) 1 redis> SETNX job "code-farmer" # 尝试覆盖 job ,失败 (integer) 0 redis> GET job # 没有被覆盖 "programmer"
在Redis中,SETNX
是 “Set If Not Exists”(如果不存在,则设置)的缩写。这是一个原子操作,用于设置一个键的值,前提是这个键不存在。如果键已经存在,.则不会执行任何操作。
封装方法trylock
,用于获取分布式锁
/** * 尝试获 取一个锁。 * * @param name 锁的名称,通常是一个资源的标识。 * @param expire 锁的过期时间,单位为毫秒。 * @return 如果获取锁成功,返回一个唯一的token;如果失败,则返回null。 */ public String tryLock(String name, long expire) { // 为锁名称添加后缀,以避免命名冲突 name = name + "_lock"; // 生成一个唯一的token,用于标识持有锁的客户端 String token = UUID.randomUUID().toString(); // 获取Redis连接工厂 RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory(); // 获取Redis连接 RedisConnection conn = factory.getConnection(); try { // 使用SET命令尝试以NX选项(只在键不存在时设置)设置键值对,如果成功,返回true // 这里使用了Expiration指定键的过期时间,以确保锁在一段时间后自动释放 // 参考redis命令:SET key value [EX seconds] [PX milliseconds] [NX|XX] Boolean result = conn.set( name.getBytes(), //key token.getBytes(), //value Expiration.from(expire, TimeUnit.MILLISECONDS), RedisStringCommands.SetOption.SET_IF_ABSENT // NX ); // 如果设置成功,返回生成的token if (result != null && result) return token; } finally { // 释放Redis连接 RedisConnectionUtils.releaseConnection(conn, factory, false); } // 如果未能成功获取锁,返回null return null; }
接下来,你可以在需要防止并发执行的方法中使用tryLock
方法:
public void exampleMethod(String taskName) { String lockKey = "myLockKey"; // 尝试获取锁 String token = tryLock(lockKey, 10000); // 锁过期时间为10秒 if (token != null) { try { // 获取锁成功,执行业务逻辑 System.out.println("所获取成功"); // 模拟任务执行 // ... } finally { // 释放锁 stringRedisTemplate.delete(lockKey+ "_lock"); } } else { // 获取锁失败,处理失败逻辑 System.out.println("获取锁失败"); } }