4. Zookeeper如何实现分布式锁

1) 规模不大的情况下
上锁: 我们可以把zNode当做一把锁,通过createNode的方式去创建节点,例如所有客户端都去创建一个节点(例如/execlusive节点)下创建临时子节点/execlusive/lock。最终只有一个节点可以创建成果,就是获得了锁。其余没有获取到锁的客户单就需要到/execlusive节点上注册一个子节点变更的watcher监听,以实时监听到lock节点的变更情况。

释放锁: 由于是临时节点,那么当这个客户端服务器宕机后,该临时节点会被自动删除;否则是在正常执行业务逻辑后,客户端会主动删除临时节点。

在规模较大时,由于一个节点释放锁需要通知所有的客户端,然后每个节点还都要再去getChildren获取当前最新值。尤其是在集群中存在若干节点同时发生watcher时,存在“羊群效应”,通信量过大,存在隐患。

2) 规模较大时

上锁:客户端都在/execlusive节点下创建临时顺序节点,这样所有客户单都可以创建成功。然后调用getChilder(/execlusive)来获取该目录下所有的子节点。客户端获取到所有子节点path后,如果自己创建的节点是序号最小的,那就认为是当前客户端获得了锁;如并非序号最小的,那就没有获得锁,并且去找到比自己小的那个节点,对其调用exist()方法,同时对其注册事件监听器。当这个被关注的节点被删除后,相应的客户端watecher会收到相应通知,此时它再去判断自己创建的节点是否是序号最小的,是就获得了锁。

解锁:业务逻辑执行完毕后主动释放锁或者客户端down掉自动释放锁。

3) 控制读写顺序的共享锁
类似于mysql的读写锁,所有读都可以共享,写却是独占的。
故所有客户端都去同一个节点下创建临时子节点,如果当前是读请求,创建的节点以R结尾(然后zk会自动加上顺序序号001一类),如果是写请求,创建的节点以W结尾(zk也会自动加上顺序序号)。
共享锁的定义是:不同事务都可以对同一个数据对象进行读取操作,而更像操作却不允许其余事务进行读或写操作。

具体执行过程
1) 先去同一个路径/shared_lock下创建临时子节点,然后对/shared_lock路径注册子节点变更的watcher监听;
2) 获取/shared_lock节点下所有的子节点,并确定自己的节点序号在所有子节点的顺序;
3) 对于写请求,只能是自身是序号最小的子节点,否则等待;对于读请求,必须是自身节点序号之前的节点都必须是读节点,即是共享读,否则也是等待。
4) 接收到watch通知后,从2步器重复执行。

释放锁是相同的

猜你喜欢

转载自blog.csdn.net/xiaohesdu/article/details/87926853
今日推荐