zookeeper学习笔记-05


六、zookeeper使用场景
1.消息订阅/发布
发布者将数据发布到zk的一个节点或者一系列节点上,订阅者进行数据订阅,当数据发生变化时,会得到数据变化的通知.
这里写图片描述

2.负载均衡
a.服务提供者将自己的域名以及ip端口的映射注册到zk中
b.服务消费者通过域名从zk中获取对应的ip端口列表 — 通过某种算法获取其中一个—dubbo.
c.当服务提供者宕机时,zk将映射关系删除(zookeeper临时节点)
这里写图片描述
3.命名服务
命名服务(Naming Service)也是分布式系统中比较常见的一种场景。在分布式系统中被命名的实体通常是集群中的机器,提供的服务地址或者远程对象,比较常见的是分布式框架(RPC,RMI)中的服务地址列表,通过命名服务,客户端能根据指定的名字获取资源的实体,服务地址和服务提供者信息。
通过zookeeper可以实现类似jndi(java naming and directory interface)的功能。

4.分布式协调/通知
通常的做法是对同一个数据节点进行watcher注册,监听数据节点的变化(数据节点本身和子节点列表),如果发生变化,所有订阅的客户端都会接收到乡音的wathcher通知,并作出相应的处理。

5.集群管理

  • 集群中正在工作的机器数量。
  • 集群中机器的运行状态
  • 集群中节点的上下线操作
  • 集群节点的统一配置

6.Master选举
利用zookeeper的强一致性,能够很好的保证在分布式高并发情况下节点的创建一定能够保证全局一致性,即zookeeper将会保证客户端无法重复创造一个已经存在的节点。也就是说如果多个客户端请求创建同一个节点, 最终只有一个客户端能够创建成功。利用这个,就可以进行master选举了。
创建成功的客户端被选举为master,并成功创建“临时节点A”,其余未创建成功的客户端slave,监听此临时节点。当master下线时,该临时节点被zookeeeper服务删除,其余的salve监听到此变化,再进行下一轮master选举。

7.分布式锁
1).排他锁(X锁,写锁)
又称为独占锁,如果事务T1对数据对象O1加上了排他锁,那么只允许T1对O1进行读取和更新操作,其他事务都不允许操作该数据对象。

a.定义锁
zookeeper通过创建一个临时数据节点来表示一个锁,如/exclusive-lock

b.获取锁
利用zookeeper的高一致性,所有客户端都请求创建/exclusive-lock这个节点,最终只有一个客户端会创建成功,那么认为这个客户端获取到了锁。那么其他没有获取到的锁的客户端会对这个节点注册一个节点变更的watcher监听,以便实时监听到lock的变更情况。

c.释放锁
由于/exclusive-lock是一个临时节点,在如下两种情况会“释放锁”

 - 获取锁的客户端服务器宕机,zookeeper会将这个临时节点移除

- 正常执行完业务逻辑后,获取锁的客户端主动删除临时节点

当/exclusive-lock节点被移除时,zookeeper会通知所有在此节点上注册监听的客户端,然后进行下一轮获取锁过程

2).共享锁(S锁,读锁)
如果事务T1对数据对象O1加上了共享锁,那么当前事务只允许对O1进行读操作,其他事务也可以对这个数据对象家共享锁,一直到该数据对象上的所有共享锁都被移除。

a).定义锁
共享锁,也是通过数据节点来表示一个锁。类似于
“/share-lock/类型-序号”的临时顺序节点 来表示一个共享所。

b).获取锁
获取锁时,都会到/share-lock下创建一个临时顺序节点。
如果是读请求: /share-lock/R-000001
如果是写请求:/share-lock/W-000003

c).判断读写顺序

  • 创建完节点后,获取/share-lock下的所有子节点,并对/share-lock注册子节点变化的watcher监听
  • 确定自己节点在所有节点中的顺序
  • 对于读请求:
    • 如果自己的序号是最小的节点,或者比自己序号小的的节点都是读请求,那么表名自己获取了共享锁,开始执行读取逻辑
    • 如果比自己序号小的的节点中有写请求,那么进入等待。
  • 对于写请求:如果自己的顺序不是最小的,那么进入等待。

d).释放锁
和排他锁的释放锁逻辑一致。

8.分布式队列
业界的分布式队列产品有许多,如ApacheMQ,kafka等消息中间件。
接下来介绍基于zookeeper实现的分布式队列

1).FIFO:先入先出*
类似于共享锁模式,大体思路很简单,就是在/queue-fifo/下创建临时顺序子节点,创建完节点后,执行顺序如下:
1. 调用getchildren(),获取所有子节点,
2. 确定自己的节点序号在所有节点中的顺序
3. 如果自己的序号不是最小的节点,那么进入等待,同时向序号最小的那个节点注册watcher监听
4. 接收到watcher监听后,重复步骤1

2).Barrier:分布式屏障*
Barrier原意是指障碍物,屏障。 在分布式系统中,规定了一个队列的所有元素必须都聚集后才能统一进行安排,否则一直等待。在分布式系统中,最终的合并计算都要基于很多并行的计算子结果来进行。设计思路如下:
开始是/queue-barrier是一个已经默认存在的节点,将其节点的数据内容赋值为一个数字n来来表Barrier值,例如n=10,表示在/queue-barrier节点下的子节点达到10个后才打开barrier.

创建完节点后根据如下五个步骤来确定执行顺序:
1. 调用getData(),/queue-barrier的数据节点内容为:10
2. 调用getchildren(),获取所有子节点,同时注册对/queue-barrier子节点变更的watcher监听
3. 统计子节点个数
4. 如果未到10,那么等待
5. 接收到watcher监听后,重复步骤1

猜你喜欢

转载自blog.csdn.net/it_freshman/article/details/79262249