Redisson 源码解析系列一:分布式锁RedissonLock可重入机制+锁续约解析

本文详细介绍了Redisson分布式锁RedissonLock的特点,包括其与setnx的优势比较,重点剖析了RedissonLock的加锁和解锁机制,以及如何实现可重入锁、锁续约和防止主从一致性问题。

1、redisson概述

Redisson是一个分布式协调Redis客服端,实现了大部分java环境下分布式对象,如锁分布式锁和同步器、对象桶(Object Bucket)、二进制流(Binary Stream)、地理空间对象桶(Geospatial Bucket)、BitSet、原子整长形(AtomicLong)、原子双精度浮点数(AtomicDouble)、话题(订阅分发)、模糊话题、布隆过滤器(Bloom Filter)、基数估计算法(HyperLogLog)等。

2、 redissonLock 比setnx有哪些优势

  • 实现可重入锁机制。
  • 实现在一定的waittime内等待重试获取锁。
  • 实现看门狗定时刷新过期时间——锁续约机制。
    • 只有用户没有设置leaseTime超时时间,那么才会使用默认的超时时间,也就是看门狗时间=30s,定时任务也是1/3 * 看门狗时间(30s)的延时任务刷新超时时间。
  • 实现多节点保存同一把锁,防止主从不一致问题。
    • redis主从结构,一般主写从读,获取锁则是写操作,当A获取锁失败,此时主从尚未同步之前,主宕机,从选举为主,此时锁没了,其他用户还能获取锁。

      在这里插入图片描述

3、分布式锁RedissonLock

RedissonLock 使用 Redis Hash 数据结构来承载锁的抢占与释放,锁标识为自定义key, 如lock:order:userID, Hash 中的 filed 由UUID.toString():Thread.currentThread().getId()拼接而成,value 值一般为 1 (重入次数自增)。

本章主要研究可重入式分布式锁RedissonLock,其JAVA 代码创建如下:

    Config config = new Config();
	config.useSingleServer().setAddress("redis://ip:6379").setPassword("123");
	Redisson redisson = Redisson.create(config);
	
    // 使用redisson 自带的分布式锁
    RLock redisLock = redissonClient.getLock("voucherOrder");
    if (!redisLock.tryLock()) {
   
   
        return Result.fail("禁止重复参与!");
    }
    try {
   
   
        IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
        return proxy.createVoucherOrder(voucherId); 
    } finally {
   
   
        redisLock.unlock();
    }

4、RedissonLock代码解析

上述例子中,主要是tryLock和unlock接口,先看tryLock接口。

    public boolean tryLock() {
   
   
        return get(tryLockAsync());
    }

    public boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException {
   
   
        return tryLock(waitTime, -1, unit);
    }

   /**
	* 等待异步回调结果,若future执行成功则返回结果。
	* 在此:返回的是
	*/
    public <V> V get(RFuture<V> future) {
   
   
        try {
   
   
            future.await();
        } catch (InterruptedException e) {
   
   
            Thread.currentThread().interrupt();
        }
        if (future.isSuccess()) {
   
   
            return future.getNow();
        }
        throw convertException(future);
    }

进入trylock()方法

// waitTime : 等待重试获取锁时间
// leaseTime : 锁超时释放事件
    public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
   
   
        long time = unit.toMillis(waitTime);
        long current = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();
        Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
        // lock acquired
        if (ttl == null) {
   
   
            return true;
        }
        
        time -= System.currentTimeMillis() - current;
        if (time <= 0) {
   
   
            acquireFailed(waitTime, unit, threadId);
            return false;
        }
        
        current = System.currentTimeMillis();
        RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
        if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
   
   
            if (!subscribeFuture.cancel(false
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值