先分享一个大佬的总结,重点都在里面:http://www.mianshigee.com
在项目中,我们一般会使用redis的setnx与expire的原子操作来完成分布式锁的设置,但是会有一个问题是这样的,我们在上游设置了一个锁,比如是mylock,并给它设置了超时时间为12s ,但是下游业务由于要进行接口请求,执行了大概20s , 这样的话就会造成业务没有执行完的情况下锁就被释放掉了,那我们该如何解决此类问题呢?
Redisson
我们可以根据redisson的可重入锁,来设置分布式锁,使用的方式和java中的ReentrantLock基本一致。并且redisson内部提供了一个监控锁的看门狗,在redisson实例被关闭前,会不断的延长锁的有效期,如果redisson实例被关闭了,那么锁时间到后自动关闭。
下面我们来一步步演示整个锁的优化过程:
1.枷锁
Rlock lock=redisson.getLock("mylock");
//常见的枷锁方式
lock.lock();
那如果加完锁之后突然宕机,岂不是这个锁一直存在?所以就有个给锁加超时自动销毁:
//给锁赋予一个最长存活期限,最长存活时间为10秒
lock.lock(10,Tomeout.SECONDS);
但是这样问题就随之而来了,我们只是设置了超时释放时间,但这并不实用啊,我们该如何监听这个锁呢?
我们来看下面的方式:
//我们尝试再来枷锁,并给锁设置一个最大超时时间
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res =lock.trylock(100,10,Tomeout.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}
这个场景解决了我们的锁释放问题,但是依然没有解决如果下游操作一直没有完成的问题,那我们就会想到,有没有一个东西可以一直监听下游操作,知道完成后进行锁的释放,中途可以给锁进行延时操作?
redisson看门狗机制
public String hello(){
//获取一把锁,只要锁的名字一样就是同一把锁
RLock lock = redisson.getLock("my-lock");
//2。加锁
// lock.lock();
//1).redisson的自动续期,如果业务超长,运行期间自动续上30s,不用担心业务时间长,锁自动过期被删掉
//2).加锁得业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s后自动删除
lock.lock(10, TimeUnit.SECONDS);//10秒以后自动解锁,自动解锁时间一定要大于业务时间
// lock.lock(10, TimeUnit.SECONDS)在锁时间到了以后,不会自动续期
//1.如果我们传递了锁的超时时间,就发送给redis执行脚本,进行站锁,默认时间就是我我们传递的时间
//2.如果我们危制定锁的超时时间,就使用lockWatchdogTimeout = 30 * 1000;看门狗默认时间
//只要站锁成功,就会启动定时任务(重新给锁设置过期时间)新的时间就是看门狗的默认时间,每10秒,都会自动续期续成满时间
//最佳实战
//1)lock.lock(10, TimeUnit.SECONDS) 省略了整个续期操作,手动解锁
try {
System.out.println("加锁成功,执行业务"+lock.getName());
Thread.sleep(30000);
} catch (Exception e){
System.out.println(e);
} finally{
//解锁
System.out.println("释放锁"+lock.getName());
lock.unlock();
}
return "hello";
}
最后附属上一个分布式锁流程图: