zookeeper实现分布式锁如何避免羊群效应问题

4 篇文章 0 订阅
2 篇文章 0 订阅

几百个jvm中只有一个会竞争锁成功,剩下99个会一直阻塞等待。第一个释放锁后,也会重新唤醒99个锁,如果临时节点一旦被删除,又给每一个jvm发出通知竞争锁,唤醒99个jvm竞争的成本非常高。

所以应该采用:

基于临时顺序节点实现临时顺序节点: 

只能按照01,02,03的顺序,也就是01会被首先竞争锁成功,然后只有01释放后,02才能获取锁成功,02会通过订阅01监听,队列形式,串行化。01消失后,02就是最小的,所以02获取锁就会成功。这一锁相当于我们的公平锁。

jvm01,jvm02,jvm03的顺序,当唤醒的时候,就会按照01,02,03的顺序来竞争锁,非常公平,防止了所有锁唤醒成本过高,以及阻塞问题。

什么是羊群效应?

当 jvm 释放锁的时候,会唤醒正在等待的 jvm 从新进入到获取锁的状态。如果正在阻塞的等待获取锁的 jvm,如果有几十个或者几百个、上千个的情况下ZkServer 端唤醒所有正在等待的 jvm,从新进入到获取锁的状态,唤醒的成本是非常高有可能会造成我们 ZkServer 端阻塞。

基于 ZK 实现分布式锁两种实现方案
1.多个 jvm 同时在 zk 上创建一个相同的临时节点,谁能够创建成功,谁就可以拿到这把锁:
存在羊群效应的 bug;
2. 基于临时顺序编号节点实现 多个 jvm 同时创建一个临时顺序编号节点,如果当前 jvm 创建的临时顺序编号节点是最小的情况下,则表示获取说成功643如果不是最小的情况下,则表示获取锁失败,就会进入到阻塞状态;当前的 jvm 订阅到我们上一个节点;
核心思想:当我们 jivm 释放锁的时候,不会通知一群正在等待获取锁的 vm,而是只会通知一个 jvm 获取锁,效率变高,对我们 zkserver 端 减去事件通知的压力
多个 jvm 抢锁,最终只会有一个 jvm 能够抢成功。
类似于: juc 并发编程中 公平锁实现原理。

伪代码实现:

1.多个 jvm 同时在 zk/lockPath 创建一个临时顺序编号节点。

2.每个 jvm 都能够创建到自己独立的临时顺序编号节点。

3.举个例子:
Jvm01 /lockPath01Jvm02 /lockPath02
Jvm03 /lockPath03

获取锁的流程:

Jvm01----
1.获取当前 jvm 创建的临时编号节点 lockPath01

2. 查询到 lockPath 下所有的子节点,实现排序 查找到最小的。3.最小的临时顺序编号节点: lockPath01
lockPath01==lockPath01 如果是小的节点情况下,则表示获取锁成功
Jvm02----

1.获取当前 jvm 创建的临时编号节点 lockPath02

2.查询到 lockPath 下所有的子节点,实现排序 查找到最小的

3.最小的临时顺序编号节点: ockPath01

4. lockPath02! =lockPath01

5. 如果当前自己创建的临时顺序编号节点不是最小的情况下,则会直接阻塞。

6.Jvm02 订阅到 lockPath01 该临时顺序编号节点。

唤醒之后:

Zk 服务器端,当 lockPath01 节点被删除之后,会通知给 jvm02Jvm02 从阻塞状态到运行状态。
1.获取当前 jvm 创建的临时编号节点 lockPath02
2.查询到 lockPath 下所有的子节点,实现排序 查找到最小的3.最小的临时顺序编号节点: lockPatho2
4. lockPath02==lockPath02 属于最小节点
5.获取锁成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值