Zookeeper是什么
Zookeeper是一个分布式协调服务的开源框架。主要用来解决分布式集群中应用系统的数据一致性问题。
- 本质上是一个分布式的小文件存储系统。
- 提供给客户端监控存储在zookeeper内部数据的功能,从⽽可以达到基于数据的集群管理目的。诸如: 统⼀命名服务(dubbo)、分布式配置管理(solr的配置集中管理)、分布式消息队列(sub/pub)、分布式锁、分布式协调等功能。
Zookeeper角色架构
zookeeper概述.png-
Leader
- Zookeeper集群工作的核心角色;
- 集群内部各个服务器的调度者;
- 事务请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性;对于 create,setData,delete 等有写操作的请求,则需要统⼀转发给leader 处理, leader 需要决定编号、执⾏操作,这个过程称为⼀个事务。
-
Follower
- 处理客户端非事务(读操作)请求。
- 转发事务给Leader。
- 参与Leader的选举投票。
-
Observer
- 观察者角色,观察 Zookeeper 集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进⾏独⽴处理,对于事务请求,则会转发给 Leader服务器进⾏处理。
- 不会参与任何形式的投票只提供非事务服务,通常⽤于在不影响集群事务处理能力的前提下提升集群的非事务处理能⼒。增加了集群增加并发的读请求。
Zookeeper的节点
Zookeeper的节点类型可以分为三大类:
- 持久性节点(Persistent)
- 临时性节点(Ephemeral)
- 顺序性节点(Sequential)
在实际创建节点的时候,会组合出四种节点类型: - 持久节点
- 持久顺序节点
- 临时节点
- 临时顺序节点
节点具体描述:
持久节点:是Zookeeper中最常⻅的⼀种节点类型,所谓持久节点,就是指节点被创建后会⼀直存在服务器,直到删除操作主动清除;
持久顺序节点:就是有顺序的持久节点,节点特性和持久节点是⼀样的,只是额外特性表现在顺序上。顺序特性实质是在创建节点的时候,会在节点名后⾯加上⼀个数字后缀,来表示其顺序;
临时节点:就是会被⾃动清理掉的节点,它的⽣命周期和客户端会话绑在⼀起,客户端会话结束,节点会被删除掉。与持久性节点不同的是,临时节点不能创建⼦节点;
临时顺序节点:就是有顺序的临时节点,和持久顺序节点相同,在其创建的时候会在名字后⾯加上数字后缀;
事务ID:在Zookeeper中,对节点数据进行更改的称为事务,概述为能够改变Zookeeper服务器状态的操作。对于每一个事务请求,Zookeeper都会为其分配一个全局唯一的事务ID,用ZXID(自增长的)表示,通常是64位的数字。每个ZXID对应一次数据的更新操作,从这些ZXID的顺序可以间接识别出Zookeeper处理这些更新操作请求的全局顺序。
节点的状态信息
[zk: localhost:2181(CONNECTED) 0] get /
cZxid = 0x0 # Create ZXID,表示节点被创建时的事务ID
ctime = Thu Jan 01 08:00:00 CST 1970 # Create Time,表示节点创建时间
mZxid = 0x0 # Modified ZXID,表示节点最后⼀次被修改时的事务ID
mtime = Thu Jan 01 08:00:00 CST 1970 # Modified Time,表示节点最后⼀次被修改的时间
pZxid = 0x3600000010 # 该节点的子节点列表最后一次修改的事务ID
cversion = 126 # 子节点的版本号
dataVersion = 0 # 内容版本号
aclVersion = 0 # 标识acl版本
ephemeralOwner = 0x0 # 表示创建该临时节点时的会话sessionID,如果是持久节点那么值为0
dataLength = 0 # 表示数据长度
numChildren = 14 # 表示直系子节点数
Watcher机制
Zookeeper使用Watcher机制实现分布式数据的发布/订阅功能
发布/订阅
发布/订阅系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当该主题对象的状态发生变化时,发布者会通知所有订阅者,使他们能够做出相应的处理。
在Zookeeper中,其允许客户端向服务端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher时,那么Zookeeper就会向指定客户端发送一个事件通知来实现分布式的通知功能。
Watcher注册通知过程.png
具体⼯作流程为:
客户端在向Zookeeper服务器注册的同时,会将Watcher对象存储在客户端的WatcherManager当中,当Zookeeper服务器触发Watcher事件后,会向客户端发送通知客户端线程从WatcherManager中取出对应的Watcher对象来执⾏回调逻辑。
Leader选举
选举机制
- 半数机制:集群存活节点达半数以上,集群可用,因此Zookeeper适合安装奇数台服务器。
- Zookeeper虽然在配置⽂件中并没有指定Master和Slave。但是,Zookeeper⼯作时,是有⼀个节点为Leader,其它为Follower,Leader是通过内部的选举机制产⽣的。
集群⾸次启动
在Zookeeper首次启动时,在这里假设是按照id值的序号来顺序启动,分析其如何进行选举。
- 首先id为1的节点启动,此时集群只有一台机器启动,该节点发出去的报文无响应,因此保持LOKKING状态。
- 接着id为2的节点启动,此时它和id为1的节点通信,互相交换⾃⼰的选举结果,由于两者都没有历史数据,所以id值较⼤的server2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例⼦中的半数以上是3),所以服务器1、2还是继续保持LOOKING状态。
- 接着id为3的节点启动,根据前面的分析得到此时id为3的节点被选举为Leader。
- 随后id为4,5的节点依次启动后,虽然它们的id值大,但是集群中已经有半数以上的节点选举了节点3为Leader,所以节点4,5只能做Follower。
集群非首次启动
每个节点在选举时都会参考⾃身节点的zxid值(事务ID);优先选择zxid值⼤的节点称Leader!!
ZAB⼀致性协议
ZAB协议是Zookeeper为了解决集群分布式数据一致性问题。
为什么要进行数据的分布式存储?在Zookeeper中有两个好处:
- 消除单点故障问题。将数据复制到多台机器上,防止一台机器宕机导致系统的不可用。
- 负载均衡。能够让分布在不同机器上的数据都能够提供对外的客户端服务,有效提高性能。
但是Zookeeper引入了数据的分布式存储时,就可能会因为各种原因产生数据不一致的情况。
因此ZAB一致性协议就是用来解决这个问题。
ZAB协议
ZK就是分布式⼀致性问题的⼯业解决⽅案,paxos是其底层理论算法(晦涩难懂著名),其中zab,raft和众多开源算法是对paxos的⼯业级实现。ZK没有完全采⽤paxos算法,⽽是使⽤了⼀种称为Zookeeper Atomic Broadcast(ZAB,Zookeeper原⼦消息⼴播协议)的协议作为其数据⼀致性的核⼼算法。
ZAB 协议是为分布式协调服务 Zookeeper 专⻔设计的⼀种⽀持崩溃恢复和原⼦⼴播协议。
ZAB的具体体现
主备模式保证⼀致性
ZK怎么处理集群中的数据?
所有客户端写⼊数据都是写⼊Leader中,然后,由 Leader 复制到Follower中。ZAB会将服务器数据的状态变更以事务Proposal的形式⼴播到所有的副本进程上,ZAB协议能够保证了事务操作的⼀个全局的变更序号(ZXID)。
广播消息
ZAB协议的消息广播过程类似于二阶段提交过程。
对于客户端提交的写请求全部由Leader接收,Leader 将请求封装成⼀个事务 Proposal(提议),将其发送给所有 Follwer ,如果收到超过半数反馈ACK,则执⾏ Commit 操作(先提交⾃⼰,再发送 Commit 给所有 Follwer)。
不能正常反馈Follower恢复正常后会进⼊数据同步阶段最终与Leader保持⼀致;
细节如下:
- Leader接收到Client请求之后,会将这个请求封装成⼀个事务,并给这个事务分配⼀个全局递增的唯⼀ ID,称为事务ID(ZXID),ZAB 协议要求保证事务的顺序,因此必须将每⼀个事务按照 ZXID进⾏先后排序然后处理。
- ZK集群为了保证任何事务操作能够有序的顺序执⾏,只能是 Leader 服务器接受写请求,即使是Follower 服务器接受到客户端的请求,也会转发到 Leader 服务器进⾏处理。
zk提供的应该是最终⼀致性的标准。zk所有节点接收写请求之后可以在⼀定时间内保证所有节点都能看到该条数据。
Leader 崩溃问题
Leader宕机后,ZK集群⽆法正常⼯作,ZAB协议提供了⼀个⾼效且可靠的leader选举算法。
Leader宕机后,被选举的新Leader需要解决的问题:
- ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。
- ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。
基于上⾯的⽬的,ZAB协议设计了⼀个选举算法:能够确保已经被Leader提交的事务被集群接受,丢弃还没有提交的事务。
这个选举算法的关键点:保证选举出的新Leader拥有集群中所有节点最⼤编号(ZXID)的事务。
网友评论