分布式锁的三种解决方案

基于数据库实现的分布式锁

实现逻辑:在数据库中创建一个表,表中包含方法名、类名等字段,并在方法名字段上创建唯一索引,当执行某个方法时,就使用这个方法名向表中插入数据,插入成功就相当于获取了锁,执行完成后删除对应的行数据释放锁。
但是要注意以下几点要求:
* 数据库的可用性和性能将直接影响分布式锁的可用性及性能。
* 锁的可重入性。同一个线程在释放锁之前,数据会一直存在,无法再次成功插入,需要在表中新增一列,用于记录当前获取到锁的服务节点和线程信息,再次获取锁的时候,先查询数据库表中服务节点和线程信息是否和当前服务节点和线程信息相同,若相同则直接获取锁。
* 锁的阻塞性。当获取不到锁,需要循环多次去获取。并设置一个超时时间,如果超过这个时间还没有获取到锁,则返回失败。

基于redis实现的分布式锁

实现逻辑:获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。

基于zookeeper实现的分布式锁

实现逻辑1:通过zookeeper创建节点时的强一致性,多个线程创建同一个节点,创建成功,表示获取锁。(该方案可能高并发情况会出现羊群效应)
实现逻辑2:
1)创建一个目录lock(随意起的节点名称);
2)线程A想获取锁就在lock目录下创建临时顺序节点;
3)获取lock目录下所有的子节点,然后获取比自己小的且属于同一级的节点(兄弟节点),如果不存在,则说明当前线程顺序号最小,获得锁;
4)线程B获取所有节点,判断自己不是最小节点,设置Watcher监听比自己次小的节点;
5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

Redis分布式锁和Zookeeper分布式锁的对比

Redis 分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能。
Zookeeper分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
posted @ 2022-04-06 18:14  OpenSir  阅读(271)  评论(0编辑  收藏  举报