用户您好!请先登录!

ZooKeeper:分布式协调服务原理

ZooKeeper:分布式协调服务原理

ZooKeeper是一种用于分布式应用程序的分布式开源协调服务。它公开了一组简单的原语,分布式应用程序可以构建这些原语,以实现更高级别的服务,以实现同步,配置维护以及组和命名。它被设计为易于编程,并使用在熟悉的文件系统目录树结构之后设计的数据模型。它在Java中运行,并且具有Java和C的绑定。

众所周知,协调服务很难做到。他们特别容易出现竞争条件和死锁等错误。ZooKeeper背后的动机是减轻分布式应用程序从头开始实施协调服务的责任。

设计目标

ZooKeeper很简单。ZooKeeper允许分布式进程通过共享的分层命名空间相互协调,该命名空间的组织方式与标准文件系统类似。名称空间由数据寄存器组成 – 在ZooKeeper用语中称为znodes – 这些与文件和目录类似。与专为存储而设计的典型文件系统不同,ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数量。

ZooKeeper实现非常重视高性能,高可用性,严格有序的访问。ZooKeeper的性能方面意味着它可以在大型分布式系统中使用。可靠性方面使其不会成为单点故障。严格的排序意味着可以在客户端实现复杂的同步原语。

ZooKeeper被复制。与它协调的分布式进程一样,ZooKeeper本身也可以在称为集合的一组主机上进行复制。

ZooKeeper服务

组成ZooKeeper服务的服务器必须彼此了解。它们维护内存中的状态图像,以及持久性存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper服务就可用。

客户端连接到单个ZooKeeper服务器。客户端维护TCP连接,通过该连接发送请求,获取响应,获取监视事件以及发送心跳。如果与服务器的TCP连接中断,则客户端将连接到其他服务器。

ZooKeeper是订购的。ZooKeeper使用反映所有ZooKeeper事务顺序的数字标记每个更新。后续操作可以使用该顺序来实现更高级别的抽象,例如同步原语。

ZooKeeper很快。它在“读取主导”工作负载中特别快。ZooKeeper应用程序在数千台计算机上运行,​​并且在读取比写入更常见的情况下表现最佳,比率大约为10:1。

数据模型和分层命名空间

ZooKeeper提供的名称空间非常类似于标准文件系统。名称是由斜杠(/)分隔的路径元素序列。ZooKeeper名称空间中的每个节点都由路径标识。

ZooKeeper的分层命名空间

ZooKeeper的分层命名空间

节点和短暂节点

与标准文件系统不同,ZooKeeper命名空间中的每个节点都可以包含与之关联的数据以及子项。这就像拥有一个允许文件也是目录的文件系统。(ZooKeeper旨在存储协调数据:状态信息,配置,位置信息等,因此存储在每个节点的数据通常很小,在字节到千字节范围内。)我们使用术语znode来说明我们正在谈论ZooKeeper数据节点。

Znodes维护一个stat结构,其中包括数据更改,ACL更改和时间戳的版本号,以允许缓存验证和协调更新。每次znode的数据更改时,版本号都会增加。例如,每当客户端检索数据时,它也接收数据的版本。

存储在命名空间中每个znode的数据以原子方式读取和写入。读取获取与znode关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表(ACL),限制谁可以做什么。

ZooKeeper也有短暂节点的概念。只要创建znode的会话处于活动状态,就会存在这些znode。会话结束时,znode将被删除。当您想要实现[tbd]时,短暂节点很有用。

有条件的更新和Watches

ZooKeeper支持观察watches的概念。客户端可以在znode上设置监视。当znode更改时,将触发并删除watches。触发监视时,客户端会收到一个数据包,指出znode已更改。如果客户端与其中一个ZooKeeper服务器之间的连接中断,则客户端将收到本地通知。

Guarantees

ZooKeeper非常快速而且非常简单。但是,由于其目标是构建更复杂的服务(如同步)的基础,因此它提供了一系列guarantees。这些是:

  • 顺序一致性 – 客户端的更新将按发送顺序应用。
  • 原子性 – 更新成功或失败。没有部分结果。
  • 单系统映像 – 无论服务器连接到哪个服务器,客户端都将看到相同的服务视图。
  • 可靠性 – 一旦应用了更新,它将从那时起持续到客户端覆盖更新。
  • 及时性 – 系统的客户视图保证在特定时间范围内是最新的。

简单的API

ZooKeeper的设计目标之一是提供一个非常简单的编程接口。因此,它仅支持以下操作:

  • create:在树中的某个位置创建一个节点
  • delete:删除节点
  • exists:测试某个位置是否存在节点
  • 获取数据:从节点读取数据
  • 设置数据:将数据写入节点
  • get children:检索节点的子节点列表
  • sync:等待传播数据

有关这些内容的更深入讨论,以及如何使用它们来实现更高级别的操作,请参阅[tbd]

Implementation

ZooKeeper Components显示ZooKeeper服务的高级组件。除请求处理器外,构成ZooKeeper服务的每个服务器都复制其自己的每个组件的副本。

ZooKeeper组件

复制数据库是包含整个数据树的内存数据库。更新将记录到磁盘以获得可恢复性,并且写入在应用于内存数据库之前会序列化到磁盘。

每个ZooKeeper服务器都为客户端服务。客户端只连接到一台服务器以提交请求。读取请求由每个服务器数据库的本地副本提供服务。更改服务状态,写请求的请求由协议协议处理。

作为协议协议的一部分,来自客户端的所有写入请求都被转发到称为领导者的单个服务器。其余的ZooKeeper服务器(称为关注者)接收来自领导者的消息提议并同意消息传递。消息传递层负责替换失败的领导者并将关注者与领导者同步。

ZooKeeper使用自定义原子消息传递协议。由于消息传递层是原子的,因此ZooKeeper可以保证本地副本永远不会发散。当领导者收到写入请求时,它会计算应用写入时系统的状态,并将其转换为捕获此新状态的事务。

用途

ZooKeeper的编程接口非常简单。但是,使用它,您可以实现更高阶的操作,例如同步原语,组成员身份,所有权等。

ZooKeeper的工作原理

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们 分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加 上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一 个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

每个Server在工作过程中有三种状态:

  • LOOKING:当前Server不知道leader是谁,正在搜寻
  • LEADING:当前Server即为选举出来的leader
  • FOLLOWING:leader已经选举出来,当前Server与之同步

1 选主流程

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有 的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:

  • 1. 1 .选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
  • 1. 2 .选举线程首先向所有Server发起一次询问(包括自己);
  • 1. 3 .选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
  • 1. 4. 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
  • 1. 5. 线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.

每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:

Zookeeper工作原理详解

fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:

Zookeeper工作原理详解

2 同步流程

选完leader以后,zk就进入状态同步过程。

  • 2. 1. leader等待server连接;
  • 2. 2 .Follower连接leader,将最大的zxid发送给leader;
  • 2. 3 .Leader根据follower的zxid确定同步点;
  • 2. 4 .完成同步后通知follower 已经成为uptodate状态;
  • 2. 5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

流程图如下所示:

Zookeeper工作原理详解

 

3 工作流程

3.1 Leader工作流程

Leader主要有三个功能:

  • 恢复数据;
  • 维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;
  • Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。

PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。

Zookeeper工作原理详解

3.2 Follower工作流程

Follower主要有四个功能:

  • 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
  • 接收Leader消息并进行处理;
  • 接收Client的请求,如果为写请求,发送给Leader进行投票;
  • 返回Client结果。

Follower的消息循环处理如下几种来自Leader的消息:

  • PING消息: 心跳消息;
  • PROPOSAL消息:Leader发起的提案,要求Follower投票;
  • COMMIT消息:服务器端最新一次提案的信息;
  • UPTODATE消息:表明同步完成;
  • REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
  • SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。

Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的。

Zookeeper工作原理详解

对于observer的流程不再叙述,observer流程和Follower的唯一不同的地方就是observer不会参加leader发起的投票。

行走的code
行走的code

要发表评论,您必须先登录