分布式Redis锁 - RedissonClient

Redis Java Client选型-Jedis Lettuce Redisson
最常用的可重入锁(Reentrant Lock) 先写个单元测试试一下
public class RedisLockTest {

    private RedissonClient redissonClient;

    //请求的key
    private static final String demo ="u001";

    //模拟短时间内的并发请求量

    private static final int threadNum =5;

    @Before
    public void init(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://120.78.144.70:6379");
        this.redissonClient = Redisson.create(config);

        System.out.println(Thread.currentThread().getName()+"是否存在key"+redissonClient.getLock(demo).isExists());
    }

    private class UserRequest implements Runnable{

        private CountDownLatch cdl;

        public UserRequest(CountDownLatch latch){
            this.cdl=latch;
        }

        @Override
        public void run() {
            try {
                if (redissonClient.getLock(demo).tryLock(0L,-1L, TimeUnit.SECONDS)) {
                    System.out.println(Thread.currentThread().getName()+"获取锁成功");
                    Thread.sleep(5000);
                    redissonClient.getLock(demo).unlock();
                    System.out.println(Thread.currentThread().getName()+"释放锁成功");
                }else{
                    System.out.println(Thread.currentThread().getName()+"获取锁失败"+"是否存在key"+redissonClient.getLock(demo).isExists());
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                //倒计时计数一次
                cdl.countDown();
            }
        }
    }

    @Test
    public void testRedissonLock(){
        CountDownLatch cdl=new CountDownLatch(threadNum);
        Executor executor = Executors.newFixedThreadPool(threadNum);
        try{
            for (int i =0; i< threadNum; i++) {
                if(i==2){
                    //模拟在业务代码没执行完毕时另一个线程获取锁
                    Thread.sleep(1500);
                }
                executor.execute(new UserRequest(cdl));
            }
            //阻塞主线程,等待所有的子线程执行完毕
            cdl.await();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

分布式锁的实现分析参考
https://www.jianshu.com/p/a8b3473f9c24

比较关注的一个参数一个是过期时间,一个是定时续约过期时间

通过阅读源码知道lesstime参数决定是否续约

    private  RFuture tryAcquireAsync(long leaseTime, TimeUnit unit, final long threadId) {
        if (leaseTime != -1L) {
            return this.tryLockInnerAsync(leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
        } else {
            RFuture ttlRemainingFuture = this.tryLockInnerAsync(this.commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(), TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
            ttlRemainingFuture.addListener(new FutureListener() {
                public void operationComplete(Future future) throws Exception {
                    if (future.isSuccess()) {
                        Long ttlRemaining = (Long)future.getNow();
                        if (ttlRemaining == null) {
                            RedissonLock.this.scheduleExpirationRenewal(threadId);
                        }

                    }
                }
            });
            return ttlRemainingFuture;
        }
    }

总结一点

if(leaseTime==-1L){
    开启自动续期的定时任务,不断重置过期时间为lockWatchdogTimeout
    定时任务的频率为lockWatchdogTimeout配置时间的1/3
}else{
    不自动续期
    设置过期时间为leaseTime
}

所有属性介绍 https://yq.aliyun.com/articles/551640/

其他锁类型的锁参考
(联锁,红锁,读写锁,信号量,可过期性信号量)
https://blog.csdn.net/l1028386804/article/details/73523810

你可能感兴趣的:(工具使用,分布式,redis锁,redisson,自动续期)