redis分布式锁各种方案以及问题点

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

简单记录这几天对分布式锁的一些认知,认知程度比较浅显。故有幸看到此文章,应当兴趣问阅读即可。


一、分布式锁的产生意义

传统的单机应用,只有单实例服务器。在面对线程安全时,仅靠Java锁即可解决线程安全问题。但在分布式架构下,多实例服务器模式下,该方案已无法满足线程同步的基本要求:同一时刻,仅有一个客户端获得锁进行资源的操作。

二、分布式锁的各种实现方式以及存在问题

1. 先设置key value。再设置expire。

 redisTemplate.opsForValue().setIfAbsent(key,value);```
 redisTemplate.expire(key, time, TimeUnit.SECONDS);

以上两条语句不是原子性的。假如执行完第一条语句后,服务挂掉,导致key永久存在。锁无法释放。

2.同时设置 key value expire

  redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);```

---
此种方式可以避免方式1的问题,但是会出现误解锁的问题。
假设线程A获取锁,但是业务比较复杂,还未执行完后,锁已超时释放。这时线程B获得锁,执行业务。这时线程A业务结束,执行解锁命令,导致线程B持有锁被解放。

## 3.设置客户端标识

value=clientId
redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);

可以在获取锁,解锁时。首先获取客户端,如果和当前不一致,则获取锁/解锁操作失败。但还是会有原子性问题的出现。
1判断当前value值和当前客户端信息比较
2 如果相同则释放锁。
但是执行完1后,线程A由于原因挂起或者宕机,这是锁超时释放了,其他线程拿到锁了。线程A醒来后继续释放锁操作,导致其他线程持有锁被释放了。
# 三、最终解决方案(待完善中)
实现方案:在线程A获取到锁时,同时开启一个守护线程。以不超过所超时时间太多的频率(锁超时30s,那频率就10s),检查当前线程是否持有锁,如果持有那么续时间。watch dog机制。未完待续....
# 总结
分布式锁索要满足的极大条件:
1 互斥。同一时刻仅有一个客户端持有锁。
2 容错率。一个redis挂了,其他redis能够立刻支持。
3 解铃还须系铃人。哪个客户端持有锁,就有该线程释放锁。
4 无死锁。保证锁能够释放出去,避免死锁现象。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

感恩的心_Yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值