java redisson实现分布式锁

发布于:2024-12-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、springboot项目整合redisson

  1. pom依赖如下
<!--redis分布式锁-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.17.0</version>
        </dependency>
  1. yml配置文件中的redis配置如下
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        max-active: 50
        max-wait: 30000ms
        max-idle: 8
        min-idle: 5
    password: 123456
    database: 11
  1. 配置RedissonClient
@Slf4j
@Configuration
public class RedisSonConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private String port;
    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public RedissonClient redissonClient(){
        try {
            Config config = new Config();
            //单节点
            //redisSon版本是3.5,ip前面要加上“redis://”,不然会报错,3.2版本可不加
            config.useSingleServer().setAddress("redis://" + host + ":" + port);
            if (StringUtils.isBlank(password)) {
                config.useSingleServer().setPassword(null);
            } else {
                config.useSingleServer().setPassword(password);
            }
            return Redisson.create(config);
        }catch (RuntimeException e){
            log.error("Redis连接失败:",e);
            throw new RuntimeException("Redis连接失败");
        }
    }

    @Bean
    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redissonClient) {
        return new RedissonConnectionFactory(redissonClient);
    }

    /**
     * 分布式锁实例化并交给工具类
     * @param redissonClient
     */
    @Bean
    public DistributedLockerImpl redissonLocker(RedissonClient redissonClient) {
        DistributedLockerImpl locker = new DistributedLockerImpl(redissonClient);
        RedisSonLockUtils.setLocker(locker);
        return locker;
    }
}

二、利用Redisson实现分布式锁

  • 创建DistributedRedisLock类,代码如下
public interface DistributedLocker {

    //可重入锁(Reentrant Lock)
    //lock(), 拿不到lock就不罢休,不然线程就一直block
    RLock lock(String lockKey);

    //leaseTime为加锁时间,单位为秒
    RLock lock(String lockKey, long timeout);

    //timeout为加锁时间,时间单位由unit确定
    RLock lock(String lockKey, long timeout, TimeUnit unit);


    //公平锁(Fair Lock)
    //lock(), 拿不到lock就不罢休,不然线程就一直block
    RLock fairLock(String lockKey);

    //leaseTime为加锁时间,单位为秒
    RLock fairLock(String lockKey, long timeout);

    //timeout为加锁时间,时间单位由unit确定
    RLock fairLock(String lockKey, long timeout, TimeUnit unit);

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit);

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
    boolean tryLock(String lockKey, long waitTime, long leaseTime);

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
    //带时间限制的tryLock(),等待1秒钟,超时返回false.
    boolean tryLock(String lockKey, long leaseTime);

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
    boolean fairTryLock(String lockKey, long waitTime);

    //fairTryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
    //带时间限制的tryLock(),拿不到lock,返回false.
    boolean fairTryLock(String lockKey);

    //释放指定key锁
    void unlock(String lockKey);

    //释放锁
    void unlock(RLock lock);
}


@Slf4j
@Component
public class DistributedLockerImpl implements DistributedLocker {
    private RedissonClient redissonClient;

    public DistributedLockerImpl(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    //lock(), 拿不到lock就不罢休,不然线程就一直block
    @Override
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    //leaseTime为加锁时间,单位为秒
    @Override
    public RLock lock(String lockKey, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, TimeUnit.SECONDS);
        return lock;
    }

    //timeout为加锁时间,时间单位由unit确定
    @Override
    public RLock lock(String lockKey, long timeout,TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }

    //公平锁(Fair Lock)
    //lock(), 拿不到lock就不罢休,不然线程就一直block
    @Override
    public RLock fairLock(String lockKey) {
        RLock lock = redissonClient.getFairLock(lockKey);
        lock.lock();
        return lock;
    }

    //timeout为加锁时间,单位为秒
    @Override
    public RLock fairLock(String lockKey, long timeout) {
        RLock lock = redissonClient.getFairLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
        return lock;
    }

    //timeout为加锁时间,时间单位由unit确定
    @Override
    public RLock fairLock(String lockKey, long timeout,TimeUnit unit) {
        RLock lock = redissonClient.getFairLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    @Override
    public boolean tryLock(String lockKey, long waitTime, long leaseTime,TimeUnit unit) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能获得锁");
            return false;
        }
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【单位秒】
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    @Override
    public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能获得锁");
            return false;
        }
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
    //带时间限制的tryLock(),等待1秒钟,超时返回false.
    @Override
    public boolean tryLock(String lockKey, long leaseTime) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能获得锁");
            return false;
        }
        RLock lock = redissonClient.getLock(lockKey);
        try {
            if (leaseTime<1){
                leaseTime = 1L;
            }
            return lock.tryLock(1L, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }


    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【单位秒】
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    @Override
    public boolean fairTryLock(String lockKey, long waitTime) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能获得锁");
            return false;
        }
        RLock lock = redissonClient.getFairLock(lockKey);
        try {
            return lock.tryLock(waitTime,TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }

    //fairTryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
    //带时间限制的tryLock(),拿不到lock,返回false.
    @Override
    public boolean fairTryLock(String lockKey) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能获得锁");
            return false;
        }
        RLock lock = redissonClient.getFairLock(lockKey);
        try {
            return lock.tryLock();
        } catch (Exception e) {
            return false;
        }
    }

    //释放指定key锁
    @Override
    public void unlock(String lockKey) {
        if (StringUtils.isBlank(lockKey)){
            log.error("传递lockKey字符串为空,不能进行解锁");
            return;
        }
        RLock lock = redissonClient.getLock(lockKey);
        if(lock.isLocked()){
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    //释放锁
    @Override
    public void unlock(RLock lock) {
        if (lock!=null){
            if(lock.isLocked()){
                if(lock.isHeldByCurrentThread()){
                    lock.unlock();
                }
            }
        }
    }
}


  • RedisSonLockUtils 工具类

public class RedisSonLockUtils {
    private static DistributedLocker locker;

    public static void setLocker(DistributedLocker locker) {
        RedisSonLockUtils.locker = locker;
    }


    //lock(), 拿不到lock就不罢休,不然线程就一直block
    public static RLock lock(String lockKey) {
        return locker.lock(lockKey);
    }

    //leaseTime为加锁时间,单位为秒
    public static RLock lock(String lockKey, long leaseTime) {
        return locker.lock(lockKey,leaseTime);
    }

    //timeout为加锁时间,时间单位由unit确定
    public static RLock lock(String lockKey, long timeout,TimeUnit unit) {
        return locker.lock(lockKey,timeout,unit);
    }



    //公平锁(Fair Lock)
    //lock(), 拿不到lock就不罢休,不然线程就一直block
    public static RLock fairLock(String lockKey) {
        return locker.fairLock(lockKey);
    }

    //timeout为加锁时间,单位为秒
    public static RLock fairLock(String lockKey, long timeout) {
        return locker.fairLock(lockKey,timeout);
    }

    //timeout为加锁时间,时间单位由unit确定
    public static RLock fairLock(String lockKey, long timeout,TimeUnit unit) {
        return locker.fairLock(lockKey,timeout,unit);
    }



    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    public static boolean tryLock(String lockKey, long waitTime, long leaseTime,TimeUnit unit) {
      return locker.tryLock(lockKey,waitTime,leaseTime,unit);
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
    public static boolean tryLock(String lockKey,long waitTime, long leaseTime) {
        return locker.tryLock(lockKey,waitTime,leaseTime);
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
    //带时间限制的tryLock(),等待1秒钟,超时返回false.
    public static boolean tryLock(String lockKey,long leaseTime) {
        return locker.tryLock(lockKey,leaseTime);
    }

    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    public static boolean fairTryLock(String lockKey, long waitTime) {
        return locker.fairTryLock(lockKey,waitTime);
    }


    //tryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
    //带时间限制的tryLock(),拿不到lock,返回false.
    public static boolean fairTryLock(String lockKey) {
        if (StringUtils.isBlank(lockKey)){
            return false;
        }
        return locker.fairTryLock(lockKey);
    }

    //释放指定key锁
    public static void unlock(String lockKey) {
        if (StringUtils.isNotBlank(lockKey)){
            locker.unlock(lockKey);
        }
    }

    //释放锁
    public static void unlock(RLock lock) {
        if (lock!=null){
            locker.unlock(lock);
        }
    }
}

三. 业务应用

 @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseVO saveChatGroup() {
      
        //群组id
        String groupId = UUIDUtils.getUUID32();
      
        RLock lock = null;
        try {
            lock = RedisSonLockUtils.fairLock(groupId);
           
         
        }catch (Exception e){
            
        }finally {
            RedisSonLockUtils.unlock(lock);
        }
    }

网站公告

今日签到

点亮在社区的每一天
去签到