redis之redission锁机制

原理

会存在一个问题:redis主节点加锁成功后去处理业务逻辑,后台同步从节点前主节点跪了造成锁丢失

底层操作redis的有lettuce、jedis、redission(也可用于分布式)

redis之redission的分布式锁,既可用于单体应用,也可用于分布式项目

对于分布式锁的操作和在单体应用中使用JUC的锁的操作是一样的

redission的可重入锁(Reentrant Lock)有看门狗机制,可解决lock.lock()死锁的问题

看门狗机制

  • 问题:lock.lock(10, TimeUnit.SECONDS),在锁时间到期后,不会自动续期,也就是看门狗机制失效不起作用

  • 1、如果我们设置了锁的超时时间,就发送redis执行脚本,来进行占锁,默认超时就是我们指定的时间。

  • 2、如果我们未指定锁的超时时间,就使用30s【LockWatchTimeout看门狗的默认时间】;

  • 只要占锁成功,就会启动一个定时任务【来重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10s就会自动再次续期,续成30s

  • internalLockLeaseTime :看门狗时间/3 ,也就是10s

  • 最佳实战:推荐使用

  • lock.lock(10, TimeUnit.SECONDS);省掉了整个续期操作,手动解锁。把过期时间调大,大于业务处理时间,防止业务超时导致锁不住其他线程

redisson加锁方式

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

推荐使用这种方式:手动解锁,可把过期时间调大,大于业务处理时间,防止业务超时导致锁不住其他线程

// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);//加这种lock方法有时间的锁,看门狗机制会失效
 
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     System.out.println("加锁成功.........执行业务"+Thread.currentThread().getId());
     Thread.sleep(10000);
   } finally {
       //解锁
       lock.unlock();
   }
}

公平锁(Fair Lock)

基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。同时还提供了异步(Async)反射式(Reactive)RxJava2标准的接口。它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒

    RLock fairLock = redisson.getFairLock("anyLock");

    // 10秒钟以后自动解锁
    // 无需调用unlock方法手动解锁
    fairLock.lock(10, TimeUnit.SECONDS);
     
    // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
    boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
    ...
    fairLock.unlock();

读写锁(ReadWriteLock)

基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口

分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。

    RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
    // 最常见的使用方法
    rwlock.readLock().lock();
    // 或
    rwlock.writeLock().lock();

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了

    // 10秒钟以后自动解锁
    // 无需调用unlock方法手动解锁
    rwlock.readLock().lock(10, TimeUnit.SECONDS);
    // 或
    rwlock.writeLock().lock(10, TimeUnit.SECONDS);
     
    // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
    boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
    // 或
    boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
    ...
    lock.unlock();
 
  • 保证一定能读到最新的数据,在修改期间,写锁是一个排他锁(互斥锁、独享锁),读锁是一个共享锁
  • 只要写锁存在没被释放,读操作就必须等待
  • 写+读:先写再读,必须等待写锁释放
  • 写+写:阻塞方式
  • 读+写:先读再写,有读锁,写也需要等待
  • 读+读:相当于无锁,并发读,只会在redis中记录好所有当前的读锁,他们都会同时加锁
  • 只要有写锁存在,读写都必须等待
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值