分布式协调服务ZooKeeper

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katherine_hsr/article/details/84982814


在分布式系统中,服务之间的协调是非常重要的,分布式系统中的leader选举、分布式锁、分布式队列等都需要通过协调服务实现。Hadoop生态系统提供了ZooKeeper。ZooKeeper通过引入类似于文件系统的层级命名空间,能够帮助用户实现leader选举、分布式锁、分布式队列等功能。

分布式协调服务的存在意义
leader 选举

在分布式系统中,常见的架构为master/slave,其中master负责集群管理,slave负责执行具体的任务(数据存储、数据处理等),如下图所示。
在这里插入图片描述
这种架构的一个常见缺点就是master为单点的,一旦master出现故障,整个集群都会出现问题,为了避免这个问题引入了多个master。例如双master:active master和standby master,其中active master对外提供服务,standby master作为备用master,一旦active maser出现问题,standby master则切换为active master。但是引入双master同样存在问题:比如说怎样选举中一个master作为active master;如何发现master出现故障;如何让standby master安全的切换为active master,从而避免集群中同时存在两个master出现混乱现象。

负载均衡

如下图所示,生产者将数据写入分布式队列,消费者从分布式消息队列中读取数据进行处理。
在这里插入图片描述
实现以上功能,需要解决两个问题:
(1) 生产者和消费者如何获取最新的消息队列的位置。因为消息队列是分布式的,其是否可用状态是动态变化的,如果某个节点出现问题对外不可用,则必须让生产者和消费者获取最新的消息队列节点的位置
(2) 如何让生产者将数据均衡的写入消息队列中的各个节点。消息队列提供了一组可存储数据的节点,需要让生产者及时了解各个节点的负载,以便将数据均衡的写入这些节点。

ZooKeeper 数据模型

考虑到分布式协调服务内部的复杂性,ZooKeeper尝试将简单的数据模型和API暴露给用户以屏蔽协调服务本身的复杂性。ZooKeeper提供了类似于文件系统的层级命名空间,在用户看来,ZooKeeper非常类似于一个分布式文件系统。
在这里插入图片描述

层级命名空间

下图是一个ZooKeeper层级命名空间,其中每个节点称为“znode”,主要包含以下几个属性:

  1. data: 每个znode拥有一个数据域用来记录用户数据,数据类型是字节数组,ZooKeeper通过多副本方式保证数据的可靠存储。
  2. type:znode类型,具体分为persistent, ephemeral, persistent_sequential和ephemeral_sequential四种基本类型
    (1) persistent:持久化节点,能够一直保存除非用户显示删除该节点
    (2) ephemeral:临时节点,该节点的生命周期与客户端相关。只要客户端保持与ZooKeeper· server·的Session·不断开,该节点就会一直存在,如果客户端与ZooKeeper· server·的Session断开了节点就会自动删除。
    (3) sequential:自动在文件名后增加的一个增量的唯一数字用来记录文件创建的顺序,常与persistent和ephemeral连用,产生persistent_sequential和ephemeral_sequential两种类型。
  3. version:znode中数据的版本号,每次数据更新会是version加一
  4. children: znode可以包含子节点,但是ephemeral类型的znode与session的生命周期是绑定的,所以ephemeral znode没有子节点。
  5. ACL:znode访问控制表,用户可单独设置每个znode的可访问用户列表,以保证znode被安全访问。
    ZooKeeper能够保证数据访问的原子性,即一个znode中的数据要么写成功,要么写失败。
Watcher

用户可以在某个znode上注册watcher以监听它的变化,一旦对应的znode被删除或者是更新,ZooKeeper将以事件的形式将变化的内容发送给监听者。watcher一旦被触发后便会被删除,如果需要用户需要再次注册watcher。

Session

session是客户端与ZooKeeper服务端之间的通信通道,同一个session中的消息是有序的。Session具有容错性,如果客户端连接的ZooKeeper服务器发生故障,客户端会自动连接到其他服务器上。

ZooKeeper 基本架构

ZooKeeper服务器通常由奇数个ZooKeeper实例构成,其中一个实例为leader, 其他实例为follower,他们同时维护了层级目录结构的一个副本,并通过ZAB(ZooKeeper Atomic Broadcast)协议维持副本间的一致性。ZooKeeper将所有数据保存到内存中,具有吞吐率高、延迟低等优点。
在这里插入图片描述

  1. ZooKeeper的读路径:所有的实例可以为客户端提供读服务,ZooKeeper的实例数目越多,读吞吐量越高。
  2. ZooKeeper的写路径:所有的实例都可以解释客户端的写请求,但需要进一步转发给leader协调完成分布式写。ZooKeeper采用了ZAB协议:只要有多数个实例写入成功,则认为本次写任务是成功的。所以在2N+1个实例的集群中,如果有N+1个实例写入成功则本次写操作就是成功的,集群的最大容忍失败的实例个数为N。需要注意的是,ZooKeeper实例越多,写延迟越高。
    当leader出现故障时,ZooKeeper会通过ZAB协议发起新一轮的leader投票选举,保证集群中始终有一个可用的leader。
    ZooKeeper中多个实例内存数据并不是强一致的,为了让客户端读到最新数据,需要给对应的ZooKeeper发送同步指令,强制其与leader同步数据。
    在ZooKeeper集群中,随着ZooKeeper实例的增多,读吞吐率升高,但写延迟增加,为了解决集群扩展导致写性能下降的问题,ZooKeeper引入了第三个角色:Observer。Observer的功能与follower类似,可以接入正常的ZooKeeper集群,接收并处理客户端读请求,或将写请求进一步转发给leader处理。Observer自身能够保存一份数据提供读服务,因此可通过增加Observer实例数提高系统的读吞吐率。由于Observer不参与投票过程,因此它出现故障并不会影响ZooKeeper集群的可用性。
    Observer常见应用常见:
    (1) 作为数据中心间的桥梁:由于数据中心间的通信延迟,将一个ZooKeeper部署到两个数据中心会误报网络故障和网络分区导致ZooKeeper不稳定。如果将整个ZooKeeper集群部署到单独一个集群中,另一个集群只部署Observer就能解决这个问题,如下图所示:
    在这里插入图片描述
    (2) 作为消息总线
    可将ZooKeeper作为一个可靠的消息总线使用,动态的在ZooKeeper集群中插入Observer,通过内置的发布订阅机智近实时的获取最新的消息。
ZooKeeper 应用
leader 选举

在这里插入图片描述
基于ZooKeeper的leader选举流程如下:
(1) 各实例启动后,尝试在ZooKeeper上创建ephemeral类型znode节点/current/leader, 假设实例B创建成功,则将自己的信息写入该znode,并将自己的角色标记为leader,开始执行leader相关的初始化工作。
(2) 其他实例像/current/leader注册watcher,并将自己的角色标注为follower,并开始执行follower相关的初始化工作。
(3) 系统正常运行,直到B发生故障退出,ZooKeeper将znode节点/current/leader删除,其他follower通过watcher收到其他节点被删除的事情,重新开始步骤1开始新一轮的leader选举。

分布式队列

在分布式系统中常见的做法是用户将作业提交给master,master将任务划分为子任务然后调度给各个Worker执行,这种方法存在的一个问题是master维护了所有的作业和Worker信息,一旦master出现故障则整个集群不可用。为了避免Master维护过多的状态,一种方法是将所有的信息都保存在ZooKeeper上,进而让master变得无状态,也使得leader选举过程更加容易。如图所示:
在这里插入图片描述
该方法是借助ZooKeeper实现了一个分布式队列,并借助ZooKeeper自带的特性,维护作业提交顺序,作业优先级,以及各个节点的负载情况。借助ZooKeeper的PersistentSequentialZnode自动编号特性,可以实现一个简易的FIFO队列,在这个队列中编号小的总是先于编号大的作业提交。

负载均衡

下图描述了Kafka通过ZooKeeper解决负载均衡和服务发现问题的,在Kafka中,各个broker和consumer都会像ZooKeeper注册,保存自己的相关信息,组件直接可以动态获取对方信息。
在这里插入图片描述
broker和consumer主要在ZooKeeper中写入以下信息:
(1) broker 节点注册信息:保存了该broker所在的host以及对外开放的端口号
(2) consumer注册信息:保存了consumer group中各个consumer当前正在读取各个topic及对应的数据流
(3) consumer offse 追踪信息: 保存了特定consumer group当前读取到的特定topic中特定分片的偏移量值

猜你喜欢

转载自blog.csdn.net/Katherine_hsr/article/details/84982814