分布式锁的实现(二)zookeeper篇

分布式锁的实现(一)Redis篇

一、关于zookeeper

我们知道zookeeper主要服务于分布式系统,它为我们提供了以下几种服务:统一配置管理统一命名服务集群管理分布式锁。本文我们主要来谈谈分布式锁的部分。

zookeeper和redis一样,都是C/S架构,且zookeeper的数据结构和Unix十分类似,可以看做是一颗树,树上的节点称为ZNode,每个节点可以通过路径进行标识,其中根节点为/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2tQGpXvi-1659942537690)(E:/Blog/lansg/source/img/image-20220803180334820.png)]

ZNode节点分为四类:

  • 持久节点:客户端断开连接后仍然存在。
  • 持久顺序节点:带编号的持久节点。
  • 临时节点:客户端断开连接后节点会消失。
  • 临时顺序节点:带编号的临时节点。

在zk中,同一路径下的同名节点只能有一个,可以通过监听器watcher监听ZNode数据变化子节点的增减变化。zk实现分布式锁就用到了以上两点,接下来我们看看具体是如何实现的。


二、zookeeper实现分布式锁

1.通过持久节点实现(不可行)

和上篇一样,我们仍然以秒杀场景下的扣减库存为例。

假设现在库存为1,有主机A和主机B同时要进行扣减库存的操作。我们可以通过zk中同一路径下同名节点的唯一性,来实现锁的效果,具体实现如下:

在主机A、B在扣减库存之前,先让其去创建一个同名节点。谁先创建了这个节点,就代表谁获得了锁,此时另一个主机再去创建该节点就会报错。假设A创建了该节点,名为lock,那么此时B就会被阻塞,并监听该节点的删除事件,直到A删除该节点(也就是释放锁)之后,才能进行下一步操作(获取锁,然后扣减库存)。

但是这样有一个很明显的问题,如果A获取锁之后宕机了怎么办?那么A将永远不会释放锁,从而造成死锁!假如我们现在有很多台服务器同时监听这个节点,那么当其释放的时候,所有服务器都会收到通知,但最终只有一个能获得锁,这会占用网络带宽和服务资源。

为了解决以上问题,往往采用第二种方案。

2.通过临时顺序节点实现(推荐)

持久节点换为临时节点,这样保证了就算宕机,节点也能够得到释放,不至于死锁。并且因为是顺序的,我们可以让每个服务器只监听他的前一个服务器创建的节点,所以释放锁的时候也就是一个一个的释放下去了。

每个节点都是有一个编号的,所以我们不需要再通过同名节点的唯一性来实现锁,具体实现如下:

  • 当服务器1获取锁时,会创建一个临时顺序节点lock1(假设该节点编号为1),然后查找根节点下所有的临时顺序节点并对其进行排序,如果自己创建的节点是所有临时顺序节点中编号最小的节点,那么成功获取锁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0hSD23xJ-1659942537691)(E:/Blog/lansg/source/img/image-20220808145256624.png)]

  • 此时服务器2也要获取锁,于是创建了一个lock2(编号为2)的节点,同样查找所有节点并排序,此时临时顺序节点有lock1和lock2,而lock1是最小的节点,所以服务器2会进入等待状态,并注册watcher监听lock1是否删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-osHAtkLC-1659942537691)(E:/Blog/lansg/source/img/image-20220808145224236.png)]

  • 这样,每来一个要获取锁的就按照这样的规则创建、监听节点,从而实现分布式锁。

三、存在的缺点

从上文我们知道,zk是通过创建、删除节点来实现分布式锁的。

这就意味着zk的性能上没有redis那么高,因为每次获取锁和释放锁都需要动态的对节点进行操作。并且在集群中,zk创建和删除节点只能通过Leader服务器来执行,然后将数据同步到所有的Follower机器上。

由于创建的是临时节点,在网络抖动导致连接断开时,zk服务器会以为客户端挂掉了,就会删除临时节点,这时候其他客户端就可以获取到锁了。不过这不是很常见,因为zk有心跳检测重试机制,在多次重试不行才会删除临时节点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值