目录
概述
ZooKeeper 是一个开源的分布式协调服务,它的设计目标是为那些高吞吐的大型分布式系统提供一个高性能、高可用、且具有严格顺序访问控制 能力的分布式协调服务,并以一系列简单易用的接口提供给用户使用。
ZooKeeper 将数据存全量储在内存中以保持高性能,并通过服务集群来实现高可用,由于 Zookeeper 的所有更新和删除都是基于事务的,所以其在读多写少的应用场景中有着很高的性能表现。
简单来说zookeeper就是动物园管理者,管理协调大数据里面的一堆组件,比如hadoop、hive、habse等等。Zookeeper 可以用于实现分布 式系统中常见的发布/订阅、负载均衡、命令服务、分布式协调/通知、集群管理、Master 选举、分布式 锁和分布式队列等功能。
特点
- 顺序一致性:从一个客户端发起的事务请求,最终都会严格按照其发起顺序被应用到 Zookeeper 中;
- 原子性:所有事务请求的处理结果在整个集群中所有机器上都是一致的;不存在部分机器应用了该事务,而另一部分没有应用的情况,一次数据更新要么成功要么失败。
- 单一视图(全局数据一致):每个server保存相同的数据副本,无论client连接哪个server,看到的数据一致;
- 可靠性:一旦服务端成功应用了一个事务,则其引起的改变会一直保留,直到被另外一个事务所更改;
- 实时性:一旦一个事务被成功应用后,在一定时间范围内,Zookeeper 可以保证客户端立即可以读取到这个事务变更后的最新状态的数据。
- 集群中只要有半数以上节点存活,zk集群就可以正常服务,所以zk适合安装奇数台。
- 一个leader,多个follower,leader挂掉之后会从follower中重新选举。
集群配置
可以由一组 Zookeeper服务构成 Zookeeper 集群,集群中每台机器都会单独在内存中维护自身的状 态,并且每台机器之间都保持着通讯,只要集群中有半数机器能够正常工作,那么整个集群就可以正常提供服务。对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增 ID,这个 ID 反映了所有事 务请求的先后顺序。
以下是集群环境搭建!!不是单机环境
解压、安装、配置环境变量并生效这三步省略,直接修改配置:
进入conf/目录下,拷贝配置样本并进行修改:
cp zoo_sample.cfg zoo.cfg
指定数据存储目录和日志文件目录(此时还没有目录,稍后手动创建),修改后完整配置如下:
tickTime=2000
#用于计算的基础时间单元。比如 session 超时:N*tickTime;
initLimit=10
#用于集群,允许从节点连接并同步到 master 节点的初始化连接时间,以 tickTime 的倍数来表示;
syncLimit=5
#用于集群, master 主节点与从节点之间发送消息,请求和应答时间长度(心 跳机制);
dataDir=/export/server/zookeeper/data
#数据存储位置;稍后手动创建
dataLogDir=/export/server/zookeeper/logs
#日志目录;稍后手动创建
clientPort=2181
#用于客户端连接的端口,默认 2181
# server.1 这个1是服务器的标识,可以是任意有效数字,标识这是第几个服务器节点,这个标识要写到
dataDir目录下面myid文件里,如果没有myid文件要自己创建
# 指名集群间通讯端口和选举端口
server.1=linux01:2888:3888
server.2=linux02:2888:3888
server.3=linux03:2888:3888
标识节点序号
分别在三台主机的 dataDir 目录下新建 myid 文件,并写入对应的节点标识。Zookeeper 集群通过 myid 文件识别集群节点,并通过上文配置的节点通信端口和选举端口来进行节点通信,选举出 Leader 节点。
在每个服务器上的/export/server/zookeeper/下创建data目录,在里面创建myid文件并写入各自序号,这个序号必须和zoo.cfg文件的序号相同。
分别在三台主机上启动ZK集群
zkServer.sh start
集群验证
zkServer.sh status
可以看到一个leader,两个follower,那么zk集群配置成功
启动客户端
zkCli.sh
集群角色
ZK集群有一个leader和多个follower。
Leader
为客户端提供读写服务,并维护集群状态,它是由集群选举所产生的;
Follower
为客户端提供读写服务,并定期向 Leader 汇报自己的节点状态。同时也参与写操作 “过半写成功”的策略和 Leader 的选举;
Observer
为客户端提供读写服务,并定期向 Leader 汇报自己的节点状态,但不参与写操作“过 半写成功”的策略和 Leader 的选举,因此 Observer 可以在不影响写性能的情况下提升集群的读性 能。
会话
- Zookeeper 客户端通过 TCP 长连接连接到服务集群,会话 (Session) 从第一次连接开始就已经建立,之 后通过心跳检测机制来保持有效的会话状态。通过这个连接,客户端可以发送请求并接收响应,同时也 可以接收到 Watch 事件的通知。
- 关于会话中另外一个核心的概念是 sessionTimeOut(会话超时时间),当由于网络故障或者客户端主动 断开等原因,导致连接断开,此时只要在会话超时时间之内重新建立连接,则之前创建的会话依然有效。
Watcher
Zookeeper 中一个常用的功能是 Watcher(事件监听器),它允许用户在指定节点上针对感兴趣的事件注 册监听,当事件发生时,监听器会被触发,并将事件信息推送到客户端。该机制是Zookeeper 实现分布式协调服务的重要特性。
节点的值变化监听
1)在linux01主机上注册监听/sanguo 节点数据变化
[zk: localhost:2181(CONNECTED) 26] get -w /sanguo
2)在linux02主机上修改/sanguo 节点的数据
[zk: localhost:2181(CONNECTED) 1] set /sanguo "xisi"
3)观察linux01主机收到数据变化的监听
WATCHER::
WatchedEvent state:SyncConnected ype:NodeDataChanged
path:/sanguo
注意:在linux02再多次修改/sanguo的值,linux01上不会再收到监听。因为注册 一次,只能监听一次。想再次监听,需要再次注册。
节点的子节点变化监听(路径变化)
1)在 linux01 主机上注册监听/sanguo 节点的子节点变化
[zk: localhost:2181(CONNECTED) 1] ls -w /sanguo [shuguo, weiguo]
2)在 linux02 主机/sanguo 节点上创建子节点
[zk: localhost:2181(CONNECTED) 2] create /sanguo/jin "simayi"
Created /sanguo/jin
3)观察 linux01 主机收到子节点变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged
path:/sanguo
注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册
工作机制
从设计模式的角度来理解,zk是基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。
集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器。
客户端向服务端写数据流程
写请求发给leader
写请求发给follower
客户端向服务端读数据流程
由于ZK满足的是CAP中的CP,,没有满足Available,因此读出的数据可能是老数据。
选举机制
初次启动
非处次启动
集群脑裂
对于一个集群,通常多台机器会部署在不同机房,来提高这个集群的可用性。保证可用性的同时,会发生一种机房间网络线路故障,导致机房间网络不通,而集群被割裂成几个小集群。这时候子集群各自选主导致“脑裂”的情况。
过半机制是如何防止脑裂现象产生的?
ZooKeeper 的过半机制导致不可能产生 2 个 leader,因为少于等于一半是不可能产生 leader 的,这就使得不论机房的机器如何分配都不可能发生脑裂。
数据模型
Zookeeper 数据模型是由一系列基本数据单元 Znode (数据节点) 组成的节点树,其中根节点为 / ,每个节点上都会保存自己的数据和节点信息。不过和常见的文件系统不同,Zookeeper 将数据全量存储在内存中,以此来实现高吞吐,减少访 问延迟。
节点类型
Zookeeper 中节点可以分为两大类:
持久节点 :节点一旦创建,除非被主动删除,否则一直存在;
临时节点 :一旦创建该节点的客户端会话失效,则所有该客户端创建的临时节点都会被删除。
临时节点和持久节点都可以添加一个特殊的属性: SEQUENTIAL ,代表该节点是否具有递增属性。如果指定该属性,那么在这个节点创建时,Zookeeper 会自动在其节点名称后面追加一个由父节点维护的递增数字。这个递增数字可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。
节点信息
集群操作
创建节点
create [-s] [-e] path data acl #其中-s 为有序节点,-e 临时节点
创建有序节点,此时创建的节点名为指定节点名 + 自增序号:
[zk: localhost:2181(CONNECTED) 23] create -s /a "aaa"
Created /a0000000022
[zk: localhost:2181(CONNECTED) 24] create -s /b "bbb"
Created /b0000000023
[zk: localhost:2181(CONNECTED) 25] create -s /c "ccc"
Created /c0000000024
创建临时节点,临时节点会在会话过期后被删除:
[zk: localhost:2181(CONNECTED) 26] create -e /tmp "tmp"
Created /tmp
查看节点
get path [watch]
[zk: localhost:2181(CONNECTED) 31] get /hadoop
123456 #节点数据
cZxid = 0x14b
ctime = Fri May 24 17:03:06 CST 2019
mZxid = 0x14b
mtime = Fri May 24 17:03:06 CST 2019
pZxid = 0x14b
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
节点各个属性如下表。其中一个重要的概念是 Zxid(ZooKeeper Transaction Id),ZooKeeper 节点的 每一次更改都具有唯一的 Zxid,如果 Zxid1 小于 Zxid2,则 Zxid1 的更改发生在 Zxid2 更改之前。
查看节点状态
stat path [watch]
它和get类似,但不会返回节点数据内容
更新节点
[zk: localhost:2181(CONNECTED) 33] set /hadoop 345
cZxid = 0x14b
ctime = Fri May 24 17:03:06 CST 2019
mZxid = 0x14c
mtime = Fri May 24 17:13:05 CST 2019
pZxid = 0x14b
cversion = 0
dataVersion = 1 # 注意更改后此时版本号为 1,默认创建时为 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
也可以基于版本号进行更改,此时类似于乐观锁机制,当你传入的数据版本号 (dataVersion) 和当前节 点的数据版本号不符合时,zookeeper 会拒绝本次修改:
[zk: localhost:2181(CONNECTED) 34] set /hadoop 678 0
version No is not valid : /hadoop #无效的版本号
删除节点
delete path [version]
和更新节点数据一样,也可以传入版本号,当你传入的数据版本号 (dataVersion) 和当前节点的数据版 本号不符合时,zookeeper 不会执行删除操作。
[zk: localhost:2181(CONNECTED) 36] delete /hadoop 0
version No is not valid : /hadoop #无效的版本号
[zk: localhost:2181(CONNECTED) 37] delete /hadoop 1
[zk: localhost:2181(CONNECTED) 38]
要想删除某个节点及其所有后代节点,可以使用递归删除,命令为 rmr path 。
退出ZK
[zk: localhost:2181(CONNECTED) 12] quit
应用场景
统一命名服务
统一配置管理
统一集群管理
服务器动态上下线
软负载均衡
分布式锁
拜占庭将军问题(Paxos算法)
Paxos算法是一种基于消息传递且具有高度容错特性的一致性算法。解决如何快速正确的在一个分布式系统中对某个数据值达成一致,并且保证任何异常都不会破坏整个系统的一致性。
算法描述
算法流程
ZAB协议
ZAB 协议并不像 Paxos 算法那样是一种通用的分布式一致性算法,ZAB是一种特别为 Zookeeper 设计的崩溃可恢复的原子消息广播算法。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。ZAB包括以下两种模式:
崩溃恢复
当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进入恢复模式并选举产生新的 Leader 服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该 Leader 服务器完成了状态同步之后,ZAB 协议就会退出恢复模式。其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和 Leader 服务器的数据状态保持一致。
消息广播
当集群中已经有过半的 Follower 服务器完成了和 Leader 服务器的状态同步,那么整个服务框架就可以进入消息广播模式了。 当一台同样遵守 ZAB 协议的服务器启动后加入到集群中时,如果此时集群中已经存在一个 Leader 服务器在负责进行消息广播,那么新加入的服务器就会自觉地进入数据恢复模式:找到 Leader 所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。
CAP理论
ZK源码图示
小小面试题
选举机制
半数机制,超过半数的投票通过,即通过。
- 第一次启动选举规则: 投票过半数时,服务器 id 大的胜出
- 第二次启动选举规则:
EPOCH 大的直接胜出
EPOCH 相同,事务 id 大的胜出
事务 id 相同,服务器 id 大的胜出
生产集群安装多少 zk 合适?
安装奇数台。
生产经验:
- 10 台服务器:3 台 zk;
- 20 台服务器:5 台 zk;
- 100 台服务器:11 台 zk;
- 200 台服务器:11 台 zk