讲解一下redisson分布式锁

很多人喜欢把redisson继续封装成注解,不说好坏,只想说锁得粒度还是越小越好。
项目中引入包

版本使用3.11.1


            org.redisson
            redisson-spring-boot-starter
        

配置文件添加

spring.redis.cluster.nodes = xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx
spring.redis.password = passwd

示例①

@Autowired
private RedissonClient redissonClient;
public void lockTest(){
    RLock lock = redissonClient.getLock(RedisConst.LOCK_PREFIX+"lock:order:xxxxxx");
    try {
        // 这里要根据实际业务使用isLocked()
        if (lock.tryLock(5,30, TimeUnit.SECONDS)) {
            //todo 这里实现你的业务逻辑,锁使用原则,粒度越小越好
        }
    } catch (InterruptedException e) {
        System.out.println("获取锁异常");
    }finally {
        lock.unlock();
    }
}

示例②乐观锁场景

RLock lock = redissonClient.getLock(RedisConst.LOCK_PREFIX + "COMMIT_LOCK");
        boolean res=false;
        try {
            res = lock.tryLock(0, 10, TimeUnit.SECONDS);
            System.out.println(res);
            if (res){
                System.out.println("获取到锁了");
            }
            if (!res) {
                return BusinessResultModel.fail("操作太频繁!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

trylock参数说明

  • -- waitTime:第一个参数最长等待取锁时间。如果再这个时间内取到锁将返回true,如果超过这个时间还没取到锁将返回false

  • -- leastTime: 第二个参数,取到锁之后锁过期时间,当超过这个时间还没执行完业务锁将被释放。

  • -- TimeUnit: 第三个参数,时间单位。

由于代码业务得复杂性,会存在以下情况:

  • 1、三个线程并发得情况下,我们假设线程A、B、C
    A线程获取锁,B线程进来取不到锁,这个时候B线程执行到finally方法把A的锁释放了,这个时候C线程去取锁取到锁了,那么AC线程同时执行同一段代码。

解决方案:实际上不存在这个问题,因为在redisson中锁只能由当前取到锁得线程释放了,所以调用lock.unlock()不用在加判断了。

  • 2、AB两个线程非并发执行,假设A线程执行完成返回后,B线程进来了,执行了同一段代码,实际上AB两个线程是同一个请求内容。这实际是一个幂等问题。

这个时候会由于业务问题导致数据库出现脏数据。例如根据同一个订单号去生成付款单,那么将会生成两条id不一样的付款单。

解决方案:针对相同请求通过业务进行判断,以上述例子为例:条件为同一个订单号,判断该订单是否已处理,如果已处理,则直接返回处理成功。或者返回已处理。

  • 3、根据trylock的参数我们可以知道,如果我想立马获得取锁结果,只要将第一个参数设置为0即可

你可能感兴趣的:(讲解一下redisson分布式锁)