zookeeper 创建互斥锁的理解

来源:互联网 发布:网络电话会议 编辑:程序博客网 时间:2024/05/29 11:23

这里谈我对基于zookeeper 的互斥锁的理解和一些问题点。
使用的zookeeper 为apache zookeeper 3.4.9

这里首先一些锁的实现方案。

首先在zookeeper 下创建一个用于测试的父节点, 下面的所有操作都在此节点下进行。 下面也会使用master 来指锁的所有者,follower 指要竞争锁的worker
create /locktest value

1 所有竞争锁的worker 都去创建同一个节点

e.g. create /locktest/plock value

这样所有的work 都会去创建这个节点, 当然只有一个会成功。 成功的节点成为锁的持有者。然后其他follower 去watch master 状态,当master 将创建的节点的节点删除时,重新发起一轮create。

2 所有的worker 在同一个节点下创建序列 节点

e.g create -s /locktest/s value
这样的话, 这样多有的创建操作都会成功。 每个worker 在locktest 下创建了递增的节点,e.g./locktest/s0000000001, /locktest/s0000000002, 这样可以令序号最小的节点为所得持有者。follower 通过watch master 创建的节点的状态。master 要放弃锁的时候,删除创建的节点即可。 然后follower 都被唤醒, 序号最小的成为master。

3 所有的worker 在同一个节点下创建临时的, 序列节点

e.g. create -e -s /lock/s_e value,
和#2 相同, 不同之处在于,此次创建的节点时临时节点,如果session 失效, 创建的节点会自动被zookeeper 删除。 这样如果当前的master 所在的进程已经不存在, 锁仍然可以被其他的follower 获取

4 所有的worker 在同一个节点下创建临时的, 序列节点, 同时每个节点的value 使用当前sessionid

e.g. create -e -s /lock/s_e 这里是每个worker 的sessionid
在#3 的基础设置了节点sessionid, 可以知道这个节点时哪个session 创建的。

下面根据对锁一些基本功能对上面所列的方案进行一些比较。

锁的获取

所有的方案都满足

锁的释放

主动释放

所有的放在主动master 主动释放锁的请的情况下, 锁可以重新被follower 获取。

被动释放

如果当前master 死掉了, 那么他创建的锁是不是应该被释放掉。 我们这里讨论如果master 已经死了(可能是机器down),需要释放锁的情形, 只有#3,#4 可以满足,#1, #2 会造成死锁。
如果创建锁节点的操纵失败了(可能是只是客户端失败了, 也可能server 端失败, 也可能都失败了),如果是服务端失败,我们重新创建锁即可。 如果是server端成功,但是服务端失败了呢。 #1, 2,#3 造成了死锁。 #4 可以在创建的lock 前,先获取自节点,通过自节点的value 查看是不是之前有当前session的节点,如果有,那么当前节点就已经持有锁了。

锁的一个应用

目前看来#4 比较有效的解决master 挂掉和 创建锁失败的情形,这解决了部分的问题。
然而这里有的问题是, jvm 的锁( e.g. mutex) 和这里的分布式锁的实现有严格的不同。
单个jvm 的锁,可以保证坐在一特定的时刻只被一个线程持有。也就说锁定范围内的资源不会同时被不同的线程获得。
这里实现的分布式锁不同。更像一个仲裁机构,A方 和B 方 申请资源(e.g. 菜地)的仲裁。 e.g. 菜地当前是A的, 最终裁判给了B。 A 种的白菜已经快要收割了,然后以后的经营权归B。 最理想的状态是,仲裁协商A,A把自己的菜收割了,A放弃经营权,然后判给B, B 后面继续自己的经营。 然而基于zk 的以上的锁没有提供此机制。A 可能没有被通知,还没有来的及收割自己的白菜, B 就把自己的拖拉机开进了菜地种上了胡萝卜。 再重归正题, 原来master master 可能不知道自己失去锁了,或者还没来的及清理原来锁占用的资源,新的master 进入了, 这样就会导致A 出现不确定的状态。 这里就出问题了。
这就需要一个二次确认的机制,确认原来的master 结束了当前锁的任务的情况下, 新的锁的持有者才能进入。

一些可能的问题

session timeout 设置比较短,在网络状态不好,或者机器负载较高的情况下,可能引起锁的非正常失效
zookeeper server 和其他应用服务器公用服务器, 当应用服务负载高影响机器整体想能是,可能出现zookeeper server 响应变慢,引起锁失效。
每次锁的释放都会引起大量的新的watch 事件,如果集权规模较大,可能会引起性能问题。