上文我们介绍了一下 Zookeeper 的一些基本概念,在本文,我们进一步学习 Zookeeper, 对其应用场景做一定程度的介绍。
1 Zookeeper 应用一 – 配置中心
Zookeeper 如何作为配置中心?发布者将数据发布到 ZooKeeper 节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和动态更新。
注意,发布/订阅系统一般有两种设计模式,分别是推和拉模式。所谓推模式,便是服务端主动将数据更新发送给所有订阅的客户端,而拉模式是指客户端主动发起请求来获取最新数据(定时轮询)。
ZooKeeper 并没有在推拉两个模式进行二选一,而是采用了推拉相结合的方式。客户端在服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送 Watcher 事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。
示例实现
在 Zookeeper 建立一个根节点,例如 /CONFIG,代表某个配置文件。将配置文件中的信息作为根节点的子节点存储,比如配置项 timeout=3000,在 Zookeeper 中展现为: /CONFIG/timeout ,节点内容是3000。然后让所有使用到该配置信息的应用机器集成 Zookeeper 并监控 /CONFIG 的状态,一旦配置信息也就是子节点发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 中获取新的配置信息应用到系统中。
2 Zookeeper 应用二 – 命名服务
命名服务是分布式系统中比较常见的一类场景。在分布式系统中,被命名的实体通常可以是集群中的机器、提供的服务地址或远程对象等——这些我们都可以统称它们为名字,其中较为常见的就是一些分布式服务框架(如 RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。
示例实现
通过在 ZooKeepr 里创建顺序节点,能够很容易创建一个全局唯一的路径,这个路径就可以作为一个名字。实际上,ZooKeeper 的命名服务即生成全局唯一的 ID。
3 Zookeeper 应用三 – 分布式协调服务/通知
ZooKeeper 的分布式协调/通知,是一种通用的分布式系统机器间的通信方式。使用 Zookeeper 中的 Watcher 注册与异步通知机制,能够很好的实现分布式环境下不同机器,甚至不同系统之间的通知与协调,从而实现对数据变更的实时处理。
示例实现
如果机器节点发生了变化,那么所有订阅的客户端都能够接收到相应的 Watcher 通知,并做出相应
的处理。
4 Zookeeper 应用四 – Master 选举
利用 ZooKeepr 的强一致性,能够很好地保证在分布式高并发情况下节点的创建一定能够保证全局唯一性,即 ZooKeeper 将会保证客户端无法创建一个已经存在的数据单元节点。如果同时有多个客户端请求创建同一个临时节点,那么最终一定只有一个客户端请求能够创建成功。
示例实现
成功创建该节点的客户端所在的机器就成为了 Master。同时,其他没有成功创建该节点的客户端,都会在该节点上注册一个子节点变更的 Watcher,用于监控当前 Master 机器是否存活,一旦发现当前的 Master 挂了,那么其他客户端将会重新进行 Master 选举。
5 Zookeeper 应用五 – 分布式锁
使用 Zookeeper 使用分布式锁具有高可用,可重入,具有阻塞锁特性,可解决失效死锁问题等优点,但也存在需要频繁创建和删除节点,性能较差的问题。
示例实现
- 创建一个目录 mylock
- 想获取锁的线程在 mylock 下创建临时顺序节点,同时获取 mylock 目录下所有的子节点,获取比自己小的兄弟节点,若不存在则获得锁,否则监听排序仅比自己靠前的那个节点
- 线程处理完会删除自己的节点,排序仅比它靠后的那个节点监听变更事件,判断自己是否为最小的节点,如果是则获得锁
6 Zookeeper 应用六 – 队列管理
Zookeeper 的队列管理分同步队列,FIFO 队列两种。
- 同步队列:当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。
- FIFO 队列:和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。
示例实现
对于同步队列的实现,我们可以先建立一个 /queue,赋值为 n,表示队列的大小。然后每个队列成员加入时,就判断是否达到队列要求的大小,如果是可以进行下一步动作,否则继续等待队列成员的加入。比较典型的情况是,当一个大的任务可能需要很多的子任务完成才能开始进行。