ZooKeeper之入门概述与原理

一、ZooKeeper定义

ZooKeeper是一个开源的分布式协调服务。
ZooKeeper是一个典型的分布式数据一致性的解决方案。分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。

二、ZooKeeper特点

(一)顺序一致性:从同一个客户端发起的事务请求,最终将会严格按照其发起顺序被应用到ZooKeeper中。
(二)可靠性:一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会被一直保留下来,除非有另一个事务又对其进行了变更。
(三)实时性:ZooKeeper仅仅保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态
(四)单一视图:无论客户端连接的是哪个ZooKeeper服务器,其看到的服务端数据模型都是一致的。
(五)原子性:所有事务请求的结果在集群中所有机器上的应用情况是一致的,也就是说要么整个集群所有集群都成功应用了某一个事务,要么都没有应用,一定不会出现集群中部分机器应用了该事务,而另外一部分没有应用的情况。

三、ZooKeeper结构

(一)文件结构
Zookeeper会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统,如图所示

在这里插入图片描述

(二)结点结构
Zookeeper这种数据结构有如下这些特点:
1、每个子目录项如NameService都被称作为znode,这个znode是被它所在的路径唯一标识,如Server1这个znode的标识为/NameService/Server1。
2、znode可以有子节点目录,并且每个znode可以存储数据,注意EPHEMERAL(临时的)类型的目录节点不能有子节点目录。
3、znode是有版本的(version),每个znode中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据,version号自动增加。
4、znode的类型:
- 持久节点(PERSISTENT)
持久节点,创建后一直存在,直到主动删除此节点。

- 持久有序节点(PERSISTENT_SEQUENTIAL)
持久顺序节点,创建后一直存在,直到主动删除此节点。在ZK中,每个父节点会为它的第一级子节点维护一份时序,记录每个子节点创建的先后顺序。

- 临时节点(EPHEMERAL)
临时节点在客户端会话失效后节点自动清除。临时节点下面不能创建子节点。

- 临时有序节点(EPHEMERAL_SEQUENTIAL)
临时节点在客户端会话失效后节点自动清除。临时节点下面不能创建子节点。父节点getChildren会获得顺序的节点列表。

5、znode可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个是Zookeeper的核心特性,Zookeeper的很多功能都是基于这个特性实现的。

四、Client与Zookeeper连接session

Session是指客户端会话,在讲解客户端会话之前,我们先来了解下客户端连接。在ZooKeeper中,一个客户端连接是指客户端和ZooKeeper服务器之间的TCP长连接。

ZooKeeper对外的服务端口默认是2181,客户端启动时,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期也开始了,通过这个连接,客户端能够通过心跳检测和服务器保持有效的会话,也能够向ZooKeeper服务器发送请求并接受响应,同时还能通过该连接接收来自服务器的Watch事件通知。

Session的SessionTimeout值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在SessionTimeout规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。

Client和Zookeeper集群建立连接,整个session状态变化如图所示:
在这里插入图片描述

如果Client因为Timeout和Zookeeper Server失去连接,client处在CONNECTING状态,会自动尝试再去连接Server,如果在session有效期内再次成功连接到某个Server,则回到CONNECTED状态。
注意:如果因为网络状态不好,client和Server失去联系,client会停留在当前状态,会尝试主动再次连接Zookeeper Server。client不能宣称自己的session expired,session expired是由Zookeeper Server来决定的,client可以选择自己主动关闭session。

五、ZooKeeper事务操作

在ZooKeeper中,能改变ZooKeeper服务器状态的操作称为事务操作。一般包括数据节点创建与删除、数据内容更新和客户端会话创建与失效等操作。对应每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,用ZXID表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些ZXID中可以间接地识别出ZooKeeper处理这些事务操作请求的全局顺序。

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

六、Zookeeper Water监听器

Zookeeper watch是一种监听通知机制。Zookeeper所有的读操作getData(), getChildren()和 exists()都可以设置监视(watch),监视事件可以理解为一次性的触发器,官方定义如下: a watch event is one-time trigger, sent to the client that set the watch, whichoccurs when the data for which the watch was set changes。Watch的三个关键点:

(一)One-time trigger(一次性触发)
当设置监视的数据发生改变时,该监视事件会被发送到客户端,例如,如果客户端调用了getData("/znode1", true) 并且稍后 /znode1 节点上的数据发生了改变或者被删除了,客户端将会获取到 /znode1 发生变化的监视事件,而如果 /znode1 再一次发生了变化,除非客户端再次对/znode1 设置监视,否则客户端不会收到事件通知。

(二)Sent to the client(发送至客户端)
Zookeeper客户端和服务端是通过 socket 进行通信的,由于网络存在故障,所以监视事件很有可能不会成功地到达客户端,监视事件是异步发送至监视者的,Zookeeper 本身提供了顺序保证(ordering guarantee):即客户端只有首先看到了监视事件后,才会感知到它所设置监视的znode发生了变化(a client will never see a change for which it has set a watch until it first sees the watch event)。
网络延迟或者其他因素可能导致不同的客户端在不同的时刻感知某一监视事件,但是不同的客户端所看到的一切具有一致的顺序。

(三)The data for which the watch was set(被设置 watch 的数据)
这意味着znode节点本身具有不同的改变方式。你可以想象 Zookeeper 设置的不同监视返回不同的数据,getData() 和 exists() 返回znode节点的相关信息,而getChildren() 返回子节点列表。因此,setData() 会触发设置在某一节点上所设置的数据监视(假定数据设置成功),而一次成功的create() 操作则会出发当前节点上所设置的数据监视以及父节点的子节点监视。一次成功的 delete操作将会触发当前节点的数据监视和子节点监视事件,同时也会触发该节点父节点的child watch。
Zookeeper 中的监视是轻量级的,因此容易设置、维护和分发。当客户端与 Zookeeper 服务器失去联系时,客户端并不会收到监视事件的通知,只有当客户端重新连接后,若在必要的情况下,以前注册的监视会重新被注册并触发,对于开发人员来说这通常是透明的。只有一种情况会导致监视事件的丢失,即:通过exists()设置了某个znode节点的监视,但是如果某个客户端在此znode节点被创建和删除的时间间隔内与zookeeper服务器失去了联系,该客户端即使稍后重新连接 zookeeper服务器后也得不到事件通知。

七、ZooKeeper集群架构

(一)角色与状态分类
领导者(leader),负责进行投票的发起和决议,更新系统状态
学习者(learner),包括跟随者(follower)观察者(observer)

  • follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
  • observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度

客户端(client),请求发起方
    在这里插入图片描述

在这里插入图片描述
    
(二)结点工作状态
LOOKING:当前Server不知道leader是谁,正在搜寻。
LEADING:当前Server即为选举出来的leader。
FOLLOWING:leader已经选举出来,当前Server与之同步。
OBSERVING:observer的行为在大多数情况下与follower完全一致,但是他们不参加选举和投票,而仅仅接受(observing)选举和投票的结果。

(三)ZAB消息处理协议
ZooKeeper并没有完全采用Paxos算法,而是使用了一种称为ZooKeeper Atomic Broadcast(ZAB,ZooKeeper原子广播协议)的协议作为其数据一致性的核心算法
ZAB协议并不像Paxos算法和Raft协议一样,是通用的分布式一致性算法,它是一种特别为ZooKeeper设计的崩溃可恢复的原子广播算法。

ZAB协议的核心是定义了对应那些会改变ZooKeeper服务器数据状态的事务请求的处理方式,称为两段提交协议,即:
所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而剩下的其他服务器则成为Follower服务器。Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提案)并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,Leader就会再次向所有的Follower服务器分发Commit消息,要求对刚才的Proposal进行提交。

ZAB协议包括两种基本的模式,分别是崩溃恢复消息广播。在整个ZooKeeper集群启动过程中,或是当Leader服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB协议就会进入恢复模式并选举产生新的Leader服务器。当选举产生了新的Leader服务器,同时集群中有过半的机器与该Leader服务器完成了状态同步之后,ZAB协议就会退出恢复模式。其中,状态同步是指数据同步,用来保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致。

崩溃恢复模式包括两个阶段:Leader选举数据同步

当集群中有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个集群就可以进入消息广播模式了。

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

  1. 选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
  2. 选举线程首先向所有Server发起一次询问(包括自己);
  3. 选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
  4. 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
  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会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。

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

(五)Leader与follower工作流程

1、Leader工作流程
Leader主要有三个功能:

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

PING消息是指follower的心跳信息;REQUEST消息是follower发送的提议信息,包括写请求及同步请求;
ACK消息是follower的对提议的回复,超过半数的follower通过,则commit该提议;
REVALIDATE消息是用来延长SESSION有效时间。

2、Follower工作流程
Follower主要有四个功能:

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

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

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

八、Zookeeper应用场景

(一)数据发布与订阅(配置中心)
(二)命名服务
(三)分布式协调/通知
(四)心跳检测
(五)工作进度汇报
(六)Master选举(客户端中主节点的选举)
(七)分布式锁





参考:
[1] ZooKeeper原理与应用
[2] ZooKeeper基本原理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值