分布式锁原理

一、分布式锁基本原理

比如,我们现在有这么多商品服务,现在都要查数据库,现在我们约定只有一个人能查数据库,查完以后放到缓存里面。

这样呢,所有服务都要进来,需要抢占一个锁,本地情况下,我们可以使用语法比如synchronize(this)锁住当前对象,只要大家用的是一个对象,就能锁住了

在分布式情况下也一样,我们this在分布式情况下,肯定没得用

但是,我们可以考虑现实生活中的一个例子,比如,我们几千个人都去上公共厕所,里面只有一个坑位,那如何保证他们有序的进行,就是说,只要我进来了,我就给这个厕所上把锁,那别人就不能进来了。然后,上完以后,再出门解锁,这样其他人又能进来了。 

所以,我们分布式锁,也是这个思想原理,所有的商品服务,无论你是哪一个实例,大家都去一个公共的地方占锁,如果占到了锁,就去执行业务,如果没有站到锁的,那等待一下

当我们业务执行完了以后,然后,释放锁,这样别人就可以占到这个锁了。

我们说的这个占坑,可以去任何一个地方去占,只要大家都去公共的一个地方,比如大家都去数据库,哪怕给数据库里面插入一条记录,如果这个人插入进去了,说明是成功的,如果插入的时候,看到已经有记录了,他就不能插入成功。

1.1 使用redis测试

redis中文文档

分布式锁的基本原理,我们都尝试去一个地方占坑,能占成功就会返回ok,大家都用同一个key保存一个东西,看能不能保存成功就行了。

二、分布式锁演进-阶段一

2.1 思想

大家想要获取锁,都去redis里面占坑,假设1000个请求全进来,都先去执行第一步,全部给redis发布setnx命令获取锁,也就是说没有lock的时候,我就占,这10000个肯定只有一个能占成功。

占成功了,就获取到锁,执行业务,执行完以后,删除锁,结束。

没占成功我们可以等一下,然后,重试。

2.2 问题

假如,我们业务代码,在这执行期间,出现了异常,导致程序抛异常直接退出了,都没有执行删锁代码,别人想要再来获取锁,就没有这个坑位了。

所以,这就导致了我们的死锁问题

假如,我把删锁代码放到finally里面,这样异常也能删除。但是还有另外一种情况,就是我们的这个代码不是由于异常崩了,而是,我们代码正好执行到这,准备执行删锁的时候,我们机器断电了,我们没有执行删锁这段代码,相当于redis又没有删除锁,别人又占不到这个坑位了。

这就是我们说的第一个最严重的问题,如果我们解锁失败就会导致死锁

解决这个问题的办法是什么?

我们可以给这个锁,设置一个自动过期时间

三、分布式锁演进-阶段二

3.1 思想

为了解决死锁的问题,我们就可以给锁设置过期时间,比如30s,30s以后它会自动删除,即使我们执行业务代码,中间出现了问题,也没关系,redis会自动帮我们删除这个锁。

3.2 问题

加锁我们在设置过期时间前,出现异常或断电了,相当于我们过期时间没设置上,同样也会造成死锁。

如果加锁,和设置过期时间,是一个原子操作,就是我给redis,让它占锁的同时,加上过期时间,只要能返回ok,redis里面就说明已经加上锁,并设置上过期时间了。

返回不了,那就是加锁失败。所以,这一块失败的原因,就是我们获取锁和设置过期时间不是原子的。

四、分布式演进-阶段三

4.1 思想

我们业务代码执行成功,就来删锁,但是,假设我们当时锁设置的过期时间为10s,由于我们业务代码很耗时,比如我执行了30s,等我将要去删锁的时候,我们之前设置的锁其实已经过期了,redis里面已经没有它了。我们想要去删,我们想要去删除一个已经没有的数据还算好的,最坏的情况是这样的,别的线程看到你的线程过期了,然后,占了这个锁,然后,当你执行删锁的时候,却把别人的锁给删除了。

解决:

我们需要保证删锁的时候,删的不是别人的锁,怎么办?我们可以在占锁的时候,值指定为一个uuid,这个uuid每个人都不一样,保证每个人匹配是自己的锁才删除。

最下面的delete多余

五、分布式锁演进-阶段四

5.1 思想

5.2 问题

如果正好判断是当前值,正要删除锁的时候,锁已经过期,别人已经设置到了新值,那么我们删除的是别人的锁。

解决:

办法删除锁必须保证原子性,使用redis+Lua脚本完成

六、分布式锁演进-阶段五

6.1 思想

加锁保证原子性,解锁保证原子性

6.2 问题

锁的自动续期,假设我们业务时间超长,业务还没执行完锁给过期了,所以,我们就要在执行业务期间,给锁自动续期,最简单的操作,就是我把锁的超时时间放长一些。

七、分布式锁最终形态

7.1 压力测试

视频教程

 

  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Zookeeper分布式锁原理是利用Zookeeper的节点唯一性和监听机制实现的。当多个客户端同时请求锁时,Zookeeper会创建一个临时有序节点,节点的名称是按照一定规则生成的,同时客户端会监听自己前一个节点的变化情况。当前一个节点被删除时,代表锁已经被释放,当前客户端就可以获取锁。如果当前客户端没有获取到锁,则会监听自己前一个节点的变化情况,直到获取到锁为止。这样就可以保证在分布式环境下,同一时刻只有一个客户端能够获取到锁,从而实现分布式锁的功能。 ### 回答2: Zookeeper是一个分布式协调服务,可用于在分布式系统中实现分布式锁。它的原理如下: 1. 创建锁节点:当一个客户端想要获取一个分布式锁时,它会在Zookeeper的目录树上创建一个临时有序节点,并在节点路径中包含一个唯一的标识符。比如,客户端创建了一个名为“/lock”的节点,Zookeeper会自动将其命名为“/lock000000001”。 2. 获取锁:客户端会尝试获取锁,即查找目录中排在它前面的节点。如果当前客户端创建的节点是目录中最小的节点(即没有其他节点在它前面),则认为它获取到了锁。 3. 监听节点:如果客户端没有获取到锁,它会对前一个节点(即比它小的最大节点)进行监听。一旦该节点被删除(即表示上一个客户端释放了锁),Zookeeper会通知当前客户端。 4. 释放锁:客户端在使用完锁之后,会删除自己创建的节点。这样,下一个节点的客户端就可以尝试获取锁。 通过上述原理,Zookeeper实现了分布式锁的功能。它是基于临时有序节点的创建和监听实现的,可以保证在分布式环境下的锁的唯一性和互斥性。同时,Zookeeper还能够提供高可用性和可靠性,因为它是一个高性能的分布式协调服务,能够处理大规模分布式系统的复杂场景。 ### 回答3: Zookeeper是一个开源的分布式协调服务,可以提供高可用的服务注册与发现、配置管理、分布式锁等功能。其中,分布式锁是Zookeeper的重要特性之一。 Zookeeper的分布式锁实现原理主要涉及四个步骤: 1. 创建唯一节点:使用Zookeeper提供的API,在指定路径下创建一个唯一的临时顺序节点。每个要竞争锁的进程都会按顺序创建自己的节点。 2. 检查最小节点:通过获取指定路径下所有子节点,并将节点按顺序排序,判断自己创建的节点是否是最小节点。如果是最小节点,则表示该进程获取到了锁。 3. 监听前一个节点:如果自己创建的节点不是最小节点,则需要监听自己创建节点的前一个节点。一旦该节点被删除,表明前一个节点释放了锁,此时进程重新执行第二步来判断自己是否可以获取到锁。 4. 释放锁:当进程完成了自身的任务后,需要调用Zookeeper提供的API删除自己创建的节点,即释放锁,以便其他进程能够继续竞争获取锁的机会。 通过以上的步骤,Zookeeper实现了基于节点顺序的分布式锁机制。它能够确保同一时间只有一个进程能够获取到锁,从而实现了对共享资源的互斥访问。此外,Zookeeper还通过监听机制实现了高效的锁释放,避免了不必要的资源浪费和竞争。 需要注意的是,Zookeeper分布式锁的实现需要保证Zookeeper集群的高可用性和稳定性。只有当Zookeeper集群正常工作时,才能保证分布式锁的正确性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值