Zookeeper 实现分布式功能组件

此文是阅读link zookeeper recipes的阅读笔记

说明

exists, getData,getChildren,delete,create 均为zk客户端的对某个znode的操作。含义同名。

Zookeeper可以用来实现以下分布式功能

分布式程序栅栏

当集群某些节点需要等待其他进程时,可以使用栅栏功能阻塞自身,并且在栅栏被删除的时候接受到通知。
步骤如下 :

1)客户端调用在栅栏znode上调用exist,并设置监听器watcher
2)如果exist返回false,说明栅栏不存在,程序继续执行
3)如果exist返回true,说明栅栏存在,需要等待
4)当监听器watcher被触发的时候,回到1)

双重栅栏

以上描述了单个栅栏的实现,利用zk还可以实现双重栅栏。
双重栅栏似的分布式程序可以同步某个计算的开始和结束,当足够多的进程可以执行计算的时候,开始计算,然后等待所有的进程完成计算,一起退出计算流程。
伪代码变量说明:
b 代表栅栏znode
p 代表客户端进程,所有的客户端进程在开始计算的时候注册自己,然后准备结束计算的时候注销的自己
x 代表最少需要开始计算流程的进程数量

开始计算

create a name n=b+"/"+p
set watch: exist(b+"/ready", true)
create child: create(n, EPHEMERAL)
L = getChildren(b, false)
if fewer children in L than x, wait for watch event
else create(b+"/"+ready)

计算结束

L = getChildren(b, false)
if no children , exit
if p is only process node in L, delete(n) and exit
if p is the lowest process node in L, wait on highest process node in P
else delete(n) if still exist and wait on lowest process node in L
goto 1

在准备开始计算的时候,所有的进程在栅栏节点下创建子节点表示准备计算了,并监听ready znode 的创建,前x-1个节点等待ready znode,第x个进程创建ready znode后大家一起开始计算;
//以下没理解,纯翻译文档 X_X
在退出计算的时候,不能和准备开始计算的时候创建一个ready标记来同步,因为使用的是临时性znode,如果在计算过程中有进程失败退出的话,就会出现问题。
进程在栅栏节点没有子节点的时候退出,为了效率,你也可以使用编号最低的节点作为标记节点,所有的可以退出的进程监听编号最低节点的消失,最小编号的节点等待任一进程的节点消失,这意味着每个节点的时候只有一个进程被唤醒。

分布式队列

这个比较简单了。
首先呢,定义一个znode来hold队列(hold不会翻),叫做队列节点,取名为queue。然后在入队的时候,创建叫做queue-X的序列临时性节点,这样就可以了(主要依赖了zk自身提供的序列节点的特性),在出对的时候,getChildren()就好了。

优先级分布式队列

基本同普通队列一样,znode 的前缀用queue-YY,YY是权重,然后入队或者出队的时候通知客户端重新获取队列节点。

分布式锁

创建序列znode,然后调用getChidren,如果自己创建的节点编号是最小的,那么获取锁成功,否则监听所有编号比自己小的节点中编号最大的那个,也就是刚好编号比自己小的那个节点。
释放锁的时候,删除自己拥有的节点就好了,此时刚好比自己大的节点会接受到通知。

共享锁(读写 锁)

获取读锁

1. 创建一个名为  guid-/read- 临时序列节点
2. 调用getChildren(),同时不能设置watcher(为了避免羊群效应)
3. 如果没有子节点叫做 write- , 而且还有比自己刚创建的节点的编号还小的节点,说明获取读锁成功。
4. 否则的话,调用exists()监听锁路径下以write开头的编号第二小的节点
5. 如果exists()返回false,回到step2
6. 否则等待前述设置的监听器的通知,然后回到step2

获取写锁

1. 调用create创建一个名为  write-的临时序列节点
2. 调用getChildren(),同时不能设置watcher(为了避免羊群效应)
3. 如果不存在比自己创建的节点编号更小的节点,说明获取读锁成功。
4. 调用exists()监听所有节点编号比自己小的所有节点中编号最大的那个节点
5. 如果exists()返回false,回到step2,否则等待通知后回到step2

实现2PC和Leader Election

基本思路都差不多,就不翻译了。

总结

zk实现分布式协调主要使用的特性是

  • 对于节点的读写原子性
  • 可以创建会话节点
  • 可以创建序列节点,并且有zk来管理节点的序列号
  • 可以设置监听器:这样就可以在某件事发生的时候确保客户端收到通知

这几点可以说是zk的核心特性,灵活的组合利用可以实现多种多样的分布式协调功能,另外有一点需要注意的是,如果有多个watcher同时监听某个节点,这样在节点事件发生的时候,多个监听器同时接收到通知,此时产生羊群效应,造成系统负载不合理的增加。在编写zk应用程序的时候需要注意到这一点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值