黑马点评_分布式锁
- 逻辑说明:
线程1发生了业务阻塞,后面正常执行业务后,把线程2的锁给释放了 - 解决方案:
解决方案就是在每个线程释放锁的时候,去判断一下当前这把锁是否属于自己,如果不属于自己,则不进行锁的删除
2.2 解决误删
核心逻辑:在存入锁时,放入自己线程的标识,在删除锁时,判断当前这把锁的标识是不是自己存入的,如果是,则进行删除,如果不是,则不进行删除。
private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
@Override
public boolean tryLock(long timeoutSec) {
//获取线程标示
String threadId = ID_PREFIX + Thread.currentThread().getId();
// 获取锁
Boolean success = stringRedisTemplate.opsForValue()
.setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
- 不可重入
在同一线程无法多次获取同一把锁
在一个线程中,方法A去调方法b,需要先获取锁,再调方法b,而方法b需要先获取该锁,此时会失败,就是死锁 - 不可重试
- 超时释放
- 主从一致性
利用hash结构 多了一个 value的值,如果是同一线程,value就给+1,释放锁就-1.并且如果value=0,那就可以删了
2.2 锁重试原理
获取—得到它何时释放的时间(信号量),订阅它----在此期间就不会去重新获取锁,浪费cpu
2.3 锁超时
为什么要设置超时就释放锁? 如果redis宕机了,这时候他才能自己释放锁,避免死锁
存在哪些问题? 如果业务执行时间太长了,那这个锁它就自己会释放了,存在隐患
Redisson怎么解决呢? 利用watchdog看门狗,进行超时续约,每隔一段时间(默认30/3s)就进行依次时间刷新,也就是能一直保证这个锁不过期。如果redis宕机了,那他就不会续约,时间到了还是自己释放。
解决方案
redission提出来了MutiLock锁,使用这把锁咱们就不使用主从了,每个节点的地位都是一样的, 这把锁加锁的逻辑需要写入到每一个主丛节点上,只有所有的服务器都写入成功,此时才是加锁成功,假设现在某个节点挂了,那么他去获得锁的时候,只要有一个节点拿不到,都不能算是加锁成功,就保证了加锁的可靠性