基于Redisson的分布式锁

1、概述

什么是分布式锁?在分布式系统中,常常需要协调各个系统的动作,保证事务的一致性或者避免重复执行相同操作。如果不同的系统或是同一个系统的不同主机之间需要共享同一资源,那么系统在访问这些资源的时候,往往需要互斥来防止彼此干扰,避免造成各系统的资源不一致,这个时候,便需要使用到分布式锁。Redisson基于redis提供了我们常用的一些锁。

redisson官方发布了redisson-spring-boot-starter,具体可以参考:gitHub文档

redisson最新依赖


    org.redisson
    redisson
    3.10.5

2、特点

  • 互斥:锁的最基本特性,分布式锁需要保证不同节点不同线程互斥。
  • 死锁: 如果一个线程获得锁,但由于某些原因不能释放锁,致使其他线程永远无法获取锁,形成死锁。分布式锁必须做到避免死锁。
  • 性能: 高并发分布式系统中,线程互斥等待可能会造成性能瓶颈,需要开发人员妥善处理。
  • 锁特性:分布式锁不能只是加锁,然后一直等待。最好实现如Java Lock的一些功能如:锁判断,超时设置,可重入性等。

3、锁类型

  • 可重入锁
    可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁。
    Redisson的可重入锁RLock接口继承了java.util.concurrent.locks.Lock接口,支持锁自动过期
    public void ReentrantLock(RedissonClient redisson) {
        RLock lock = redisson.getLock("test");
        try {
            // 加锁
//            lock.lock();
            // 若没有手动释放锁,10秒钟以后自动解锁
//            lock.lock(10, TimeUnit.SECONDS);
            // 尝试加锁,最多等待3秒,上锁以后60秒自动解锁
            boolean res = lock.tryLock(3, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 手动解锁
            lock.unlock();
        }
    }

RLock继承了org.redisson.api.RLockAsync,支持异步执行

    public void AsynReentrantLock(RedissonClient redisson) {
        RLock lock = redisson.getLock("test");
        try {
//            lock.lockAsync();
//            lock.lockAsync(10, TimeUnit.SECONDS);
            Future res = lock.tryLockAsync(3, 60, TimeUnit.SECONDS);
            if (res.get()) {
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
  • 公平锁
    加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,原则是先到先得。保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。
    public void FairLock(RedissonClient redisson) {
        RLock fairLock = redisson.getFairLock("test");
        try {
//            fairLock.lock();
//            fairLock.lock(10, TimeUnit.SECONDS);
            // 尝试加锁,最多等待3秒,上锁以后60秒自动解锁
            boolean res = fairLock.tryLock(3, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            fairLock.unlock();
        }
    }
  • 联锁
    RedissonMultiLock对象可以将多个RLock关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。
    public void MultiLock(RedissonClient redisson1,RedissonClient redisson2, RedissonClient redisson3){
        RLock lock1 = redisson1.getLock("lock1");
        RLock lock2 = redisson2.getLock("lock2");
        RLock lock3 = redisson3.getLock("lock3");
        RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
        try {
            // 同时加锁lock1 lock2 lock3, 所有的锁都上锁成功才算成功。
            lock.lock();
            // 尝试加锁,最多等待10秒,上锁以后60秒自动解锁
            boolean res = lock.tryLock(10, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
  • 红锁
    RedissonRedLock对象实现了RedLock的加锁算法,其也可以将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。
public void RedLock(RedissonClient redisson1, RedissonClient redisson2, RedissonClient redisson3) {
        RLock lock1 = redisson1.getLock("lock1");
        RLock lock2 = redisson2.getLock("lock2");
        RLock lock3 = redisson3.getLock("lock3");
        RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
        try {
            // 同时加锁:lock1 lock2 lock3, 红锁在大部分节点上加锁成功就算成功。
            lock.lock();
            // 尝试加锁,最多等待10秒,上锁以后60秒自动解锁
            boolean res = lock.tryLock(10, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
  • 读写锁
    Redisson的分布式可重入读写锁RReadWriteLock继承了java.util.concurrent.locks.ReadWriteLock
    该对象允许同时有多个读取锁,但是最多只能有一个写入锁。
public void ReadLock(RedissonClient redisson){
        RReadWriteLock rwlock = redisson.getReadWriteLock("test");
        try {
            rwlock.readLock().lock();
            // 10秒钟以后自动解锁
            rwlock.readLock().lock(10, TimeUnit.SECONDS);
            // 尝试加锁,最多等待10秒,上锁以后60秒自动解锁
            boolean res = rwlock.readLock().tryLock(10, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwlock.readLock().unlock();
        }
    }

    public void WriteLock(RedissonClient redisson){
        RReadWriteLock rwlock = redisson.getReadWriteLock("test");
        try {
            rwlock.writeLock().lock();
            // 10秒钟以后自动解锁
            rwlock.writeLock().lock(10, TimeUnit.SECONDS);
            // 尝试加锁,最多等待10秒,上锁以后60秒自动解锁
            boolean res = rwlock.writeLock().tryLock(10, 60, TimeUnit.SECONDS);
            if (res) { //成功
                // do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwlock.writeLock().unlock();
        }
    }
  • Redisson官方文档

你可能感兴趣的:(基于Redisson的分布式锁)