Zookeeper
2022-12-14 09:36:08 16 举报
AI智能生成
ZK学习脑图总结
作者其他创作
大纲/内容
基本信息
常用接口
2181
生产集群安装多少 zk 合适
安装奇数台
生产经验
10台服务器:3台zk
20台服务器:5台zk
100台服务器:11台zk
200台服务器:11台zk
服务器台数多
好处:提高可靠性
坏处:提高通信延时
选举机制
基本概念
SID
SID:服务器ID。用来唯一标识一台 ZooKeeper集群中的机器,每台机器不能重 复,和myid一致。
ZXID
事务ID。ZXID是一个事务ID,用来 标识一次服务器状态的变更。在某一时刻, 集群中的每台机器的ZXID值不一定完全一 致,这和ZooKeeper服务器对于客户端“更 新请求”的处理逻辑有关。
Epoch
每个Leader任期的代号。没有 Leader时同一轮投票过程中的逻辑时钟值是 相同的。每投完一次票这个数据就会增加
第一次启动
(1)服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING
(2)服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)
大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING
大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING
(3)服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服
务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;
务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;
(4)服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;
(5)服务器5启动,同4一样当小弟。
非第一次启动
(1)当ZooKeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举
服务器初始化启动
服务器运行期间无法和Leader保持连接
(2)而当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态
集群中本来就已经存在一个Leader
对于第一种已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连 接,并进行状态同步即可。
集群中确实不存在Leader
假设ZooKeeper由5台服务器组成,SID分别为1、2、3、4、5,ZXID分别为8、8、8、7、7,并且此时SID为3的服务器是Leader。某一时刻,
3和5服务器出现故障,因此开始进行Leader选举。
3和5服务器出现故障,因此开始进行Leader选举。
选举Leader规则
1. EPOCH大的直接胜出
2. EPOCH相同,事务id大的胜出
3. 事务id相同,服务器id大的胜出
监听器原理
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目 录节点增加删除)时,ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数 据的任何改变都能快速的响应到监听了该节点的应用程序。
监听原理详解
1)首先要有一个main()线程
2)在main线程中创建Zookeeper客户端,这时就会创建两个线 程,一个负责网络连接通信(connet),一个负责监听(listener)
3)通过connect线程将注册的监听事件发送给Zookeeper
4)在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中
5)Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程
6)listener线程内部调用了process()方法
常见的监听
1)监听节点数据的变化
get path [watch]
2)监听子节点增减的变化
ls path [watch]
ZooKeeper 分布式锁案例
什么叫做分布式锁呢
比如说"进程 1"在使用该资源的时候,会先去获得锁,"进程 1"获得锁以后会对该资源保持独占,这样其他进程就无法访问该资源,"进程 1"用完该资源以后就将锁释放掉,让其 他进程来获得锁,那么通过这个锁机制,我们就能保证了分布式系统中多个进程能够有序的 访问该临界资源。那么我们把这个分布式环境下的这个锁叫作分布式锁。
分布式锁案例
1)接收到请求后,在/locks节点下创建一个临时顺序节点
2)判断自己是不是当前节点下最小的节点:是,获取到锁;不是,对前一个节点进行监听
3)获取到锁,处理完业务后,delete节点释放锁,然后下面的节点将收到通知,重复第二步判断
常见的ZooKeeper Java API
原生Java API
ZkClient
Curator
Curator 框架实现分布式锁案例
原生的 Java API 开发存在的问题
(1)会话连接是异步的,需要自己去处理。比如使用 CountDownLatch
(2)Watch 需要重复注册,不然就不能生效
(3)开发的复杂性还是比较高的
4)不支持多节点删除和创建。需要自己去递归
Curator
是一个专门解决分布式锁的框架,解决了原生 Java API 开发分布式遇到的问题
Curator 是 Apache ZooKeeper 的Java客户端库
详情请查看官方文档:https://curator.apache.org/index.html
Curator 项目的目标是简化 ZooKeeper 客户端的使用
Curator 最初是 Netfix 研发的,后来捐献了 Apache 基金会,目前是 Apache 的顶级项目
Curator API 常用操作 - Watch事件监听
ZooKeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。
ZooKeeper 中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。
ZooKeeper 原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便需要开发人员自己反复注册Watcher,比较繁琐。
Curator引入了 Cache 来实现对 ZooKeeper 服务端事件的监听
ZooKeeper提供了三种Watcher
NodeCache : 只是监听某一个特定的节点
PathChildrenCache : 监控一个ZNode的子节点.
TreeCache : 可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
分布式锁
在我们进行单机应用开发,涉及并发同步的时候,我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题,这时多线程的运行都是在同一个JVM之下,没有任何问题。
但当我们的应用是分布式集群工作的情况下,属于多JVM下的工作环境,跨JVM之间已经无法通过多线程的锁解决同步问题。
那么就需要一种更加高级的锁机制,来处理种跨机器的进程之间的数据同步问题——这就是分布式锁。
ZooKeeper分布式锁原理
核心思想
当客户端要获取锁,则创建节点,使用完锁,则删除该节点。
步骤
客户端获取锁时,在lock节点下创建临时顺序节点
然后获取lock下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。使用完锁后,将该节点删除
如果发现自己创建的节点并非lock所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件
如果发现比自己小的那个节点被删除,则客户端的Watcher会收到相应通知,此时再次判断自己创建的节点是否是lock子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听
Curator实现分布式锁API
InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
InterProcessMutex:分布式可重入排它锁
InterProcessReadWriteLock:分布式读写锁
InterProcessMultiLock:将多个锁作为单个实体管理的容器
InterProcessSemaphoreV2:共享信号量
Zookeeper入门
概述
https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html
Zookeeper 是一个开源的分布式的,为分布式框架提供协调服务的 Apache 项目。
Zookeeper存在一个问题:如果两台client,A和B,在A修改节点之后,B立即请求,有可能获取的节点值不是最新的
Sometimes developers mistakenly assume one other guarantee that ZooKeeper does not in fact make. This is:
Simultaneously Conistent Cross-Client Views
ZooKeeper does not guarantee that at every instance in time, two different clients will have identical views of ZooKeeper data. Due to factors like network delays, one client may perform an update before another client gets notified of the change. Consider the scenario of two clients, A and B. If client A sets the value of a znode /a from 0 to 1, then tells client B to read /a, client B may read the old value of 0, depending on which server it is connected to. If it is important that Client A and Client B read the same value, Client B should should call the sync() method from the ZooKeeper API method before it performs its read.
So, ZooKeeper by itself doesn't guarantee that changes occur synchronously across all servers, but ZooKeeper primitives can be used to construct higher level functions that provide useful client synchronization. (For more information, see the ZooKeeper Recipes. https://zookeeper.apache.org/doc/r3.1.2/recipes.html).
Simultaneously Conistent Cross-Client Views
ZooKeeper does not guarantee that at every instance in time, two different clients will have identical views of ZooKeeper data. Due to factors like network delays, one client may perform an update before another client gets notified of the change. Consider the scenario of two clients, A and B. If client A sets the value of a znode /a from 0 to 1, then tells client B to read /a, client B may read the old value of 0, depending on which server it is connected to. If it is important that Client A and Client B read the same value, Client B should should call the sync() method from the ZooKeeper API method before it performs its read.
So, ZooKeeper by itself doesn't guarantee that changes occur synchronously across all servers, but ZooKeeper primitives can be used to construct higher level functions that provide useful client synchronization. (For more information, see the ZooKeeper Recipes. https://zookeeper.apache.org/doc/r3.1.2/recipes.html).
Zookeeper工作机制
Zookeeper从设计模式角度来理解:是一个基 于观察者模式设计的分布式服务管理框架,它负责 存储和管理大家都关心的数据,然后接受观察者的 注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在Zookeeper上注册的那些观察 者做出相应的反应。
Zookeeper 集群角色
Leader 领导者
处理事务请求
集群内部各服务器的调度者
Follower 跟随者
处理客户端非事务请求,转发事务请求给Leader服务器
参与Leader选举投票
Observer 观察者
处理客户端非事务请求,转发事务请求给Leader服务器
概念
Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。
Zookeeper 翻译过来就是 动物园管理员,他是用来管 Hadoop(大象)、Hive(蜜蜂)、Pig(小 猪)的管理员。简称zk
Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。
Zookeeper 提供的主要功能包括:
配置管理
分布式锁
集群管理
应用场景
统一命名服务
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。
例如:IP不容易记住,而域名容易记住。
统一配置管理
分布式环境下,配置文件同步非常常见。
一般要求一个集群中,所有节点的配置信息是一致的,比如 Kafka 集群。
对配置文件修改后,希望能够快速同步到各个节点上。
配置管理可交由ZooKeeper实现
可将配置信息写入ZooKeeper上的一个Znode
各个客户端服务器监听这个Znode
一旦Znode中的数据被修改,ZooKeeper将通知 各个客户端服务器
统一集群管理
分布式环境中,实时掌握每个节点的状态是必要的
可根据节点实时状态做出一些调整
ZooKeeper可以实现实时监控节点状态变化
可将节点信息写入ZooKeeper上的一个ZNode
监听这个ZNode可获取它的实时状态变化
服务器节点动态上下线
使用临时节点可以实现服务器节点的动态上下线
软负载均衡
在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求
特点
Zookeeper:一个领导者(Leader),多个跟随者(Follower)组成的集群。
集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器。
全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。
数据更新原子性,一次数据更新要么成功,要么失败。
实时性,在一定时间范围内,Client能读到最新数据。
数据结构
ZooKeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一棵树,每个 节点称做一个 ZNode。
每一个 ZNode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过 其路径唯一标识。
这里面的每一个节点都被称为: ZNode,每个节点上都会保存自己的数据和节点信息。
节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下
节点可以分为四大类
PERSISTENT 持久化节点
客户端与Zookeeper断开连接后,该节点依旧存在
EPHEMERAL 临时节点 :-e
客户端与Zookeeper断开连接后,该节点被删除
PERSISTENT_SEQUENTIAL 持久化顺序节点 :-s
客户端与Zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
EPHEMERAL_SEQUENTIAL 临时顺序节点 :-es
客户端与Zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
说明
创建znode时设置顺序标识,znode名称 后会附加一个值,顺序号是一个单调递增的计数 器,由父节点维护
注意
在分布式系统中,顺序号可以被用于 为所有的事件进行全局排序,这样客户端可以通 过顺序号推断事件的顺序
Zookeeper 服务端常用命令
启动 ZooKeeper 服务:./zkServer.sh start
查看 ZooKeeper 服务状态: ./zkServer.sh status
停止 ZooKeeper 服务: ./zkServer.sh stop
重启 ZooKeeper 服务: ./zkServer.sh restart
客户端常用命令
连接ZooKeeper服务端
./zkCli.sh –server ip:port
断开连接
quit
显示指定目录下节点
ls 目录
获取节点详细信息
ls –s /节点path
czxid
创建节点的事务 zxid
每次修改ZooKeeper状态都会产生一个ZooKeeper事务ID。事务ID是ZooKeeper中所 有修改总的次序。每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之 前发生。
ctime
znode 被创建的毫秒数(从 1970 年开始)
mzxid
znode 最后更新的事务 zxid
mtime
znode 最后修改的毫秒数(从 1970 年开始)
pZxid
znode 最后更新的子节点 zxid
cversion
znode 子节点变化号,znode 子节点修改次数
dataversion
znode 数据变化号
aclVersion
znode 访问控制列表的变化号
ephemeralOwner
如果是临时节点,这个是 znode 拥有者的 session id。如果不是 临时节点则是 0。
dataLength
znode 的数据长度
numChildren
znode 子节点数量
创建节点
create /节点path valu
获取节点值
get /节点path
设置节点值
set /节点path value
删除单个节点
delete /节点path
删除带有子节点的节点
deleteall /节点path
创建临时节点
create -e /节点path value
创建顺序节点
create -s /节点path value
源码分析
算法基础
拜占庭将军问题
拜占庭将军问题是一个协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。问题是这些将军在地理上是分隔开来的,并且将 军中存在叛徒。叛徒可以任意行动以达到以下目标:欺骗某些将军采取进攻行动;促成一个不是所有将军都同意的决定,如当将军们不希望进攻时促成进攻 行动;或者迷惑某些将军,使他们无法做出决定。如果叛徒达到了这些目的之一,则任何攻击行动的结果都是注定要失败的,只有完全达成一致的努力才能 获得胜利。
Paxos 算法
概念
一种基于消息传递且具有高度容错特性的一致性算法
解决的问题
就是如何快速正确的在一个分布式系统中对某个数据值达成一致,并且保证不论发生任何异常, 都不会破坏整个系统的一致性。
描述
在一个Paxos系统中,首先将所有节点划分为Proposer(提议者),Acceptor(接受者),和
Learner(学习者)。(注意:每个节点都可以身兼数职)
Learner(学习者)。(注意:每个节点都可以身兼数职)
一个完整的Paxos算法流程分为三个阶段
Prepare准备阶段
Proposer向多个Acceptor发出Propose请求Promise(承诺)
Acceptor针对收到的Propose请求进行Promise(承诺)
Accept接受阶段
Proposer收到多数Acceptor承诺的Promise后,向Acceptor发出Propose请求
Acceptor针对收到的Propose请求进行Accept处理
Learn学习阶段
Proposer将形成的决议发送给所有Learners
流程
Prepare: Proposer生成全局唯一且递增的Proposal ID,向所有Acceptor发送Propose请求,这里无需携带提案内容,只携 带Proposal ID即可。
Promise: Acceptor收到Propose请求后,做出“两个承诺,一个应答”
不再接受ProposalID小于等于(注意:这里是<=)当前请求的Propose请求
不再接受Proposal ID小于(注意:这里是< )当前请求的Accept请求
不违背以前做出的承诺下,回复已经Accept过的提案中Proposal ID最大的那个提案的Value和Proposal ID,没有则
返回空值
返回空值
Propose: Proposer收到多数Acceptor的Promise应答后,从应答中选择Proposal ID最大的提案的Value,作为本次要发起的
提案。如果所有应答的提案Value均为空值,则可以自己随意决定提案Value。然后携带当前Proposal ID,向所有Acceptor发送 Propose请求
提案。如果所有应答的提案Value均为空值,则可以自己随意决定提案Value。然后携带当前Proposal ID,向所有Acceptor发送 Propose请求
Accept: Acceptor收到Propose请求后,在不违背自己之前做出的承诺下,接受并持久化当前Proposal ID和提案Value
Learn: Proposer收到多数Acceptor的Accept后,决议形成,将形成的决议发送给所有Learner
缺陷
在网络复杂的情况下,一个应用 Paxos 算法的分布式系统,可能很久无法收敛,甚至陷入活锁的情况
造成这种情况的原因是系统中有一个以上的 Proposer,多个 Proposers 相互争夺 Acceptor, 造成迟迟无法达成一致的情况。针对这种情况,一种改进的 Paxos 算法被提出:从系统中选 出一个节点作为 Leader,只有 Leader 能够发起提案。这样,一次 Paxos 流程中只有一个 Proposer,不会出现活锁的情况,此时只会出现例子中第一种情况
ZAB 协议
概念
Zab 借鉴了 Paxos 算法,是特别为 Zookeeper 设计的支持崩溃恢复的原子广播协议。基 于该协议,Zookeeper 设计为只有一台客户端(Leader)负责处理外部的写事务请求,然后 Leader 客户端将数据同步到其他 Follower 节点。即 Zookeeper 只有一个 Leader 可以发起提 案。
协议内容
消息广播
客户端发起一个写操作请求
Leader服务器将客户端的请求转化为事务Proposal 提案,同时为每个Proposal 分配一个全局的ID,即zxid
Leader服务器为每个Follower服务器分配一个单独的队列,然后将需要广播的 Proposal依次放到队列中去,并且根据FIFO策略进行消息发送
Follower接收到Proposal后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向Leader反馈一个Ack响应消息
Leader接收到超过半数以上Follower的Ack响应消息后,即认为消息发送成功,可以发送commit消息
Leader向所有Follower广播commit消息,同时自身也会完成事务提交。Follower 接收到commit消息后,会将上一条事务提交
Zookeeper采用Zab协议的核心,就是只要有一台服务器提交了Proposal,就要确保所有的服务器最终都能正确提交Proposal
崩溃恢复
引入原因,为了解决下列问题
ZAB协议针对事务请求的处理过程 类似于一个两阶段提交过程
广播事务阶段
广播提交操作
这两阶段提交模型如下,有可能因 为Leader宕机带来数据不一致,比如
Leader 发起一个事务 Proposal1后就宕机,Follower都没有 Proposal1
Leader收到半数ACK宕机, 没来得及向Follower发送Commit
异常假设
一旦Leader服务器出现崩溃或者由于网络原因导致Leader服务器失去了与过半 Follower的联系,那么就会进入崩溃恢复模式
假设两种服务器异常情况
假设一个事务在Leader提出之后,Leader挂了
一个事务在Leader上提交了,并且过半的Follower都响应Ack了,但是Leader在Commit消息发出之前挂了
Zab协议崩溃恢复要求满足以下两个要求
确保已经被Leader提交的提案Proposal,必须最终被所有的Follower服务器提交。 (已经产生的提案,Follower必须执行)
确保丢弃已经被Leader提出的,但是没有被提交的Proposal。(丢弃胎死腹中的提案)
崩溃恢复主要包含
Leader选举
根据上述要求,Zab协议需要保证选举出来的Leader需要满足以下条件
新选举出来的Leader不能包含未提交的Proposal。即新Leader必须都是已经提交了Proposal的Follower服务器节点。
新选举的Leader节点中含有最大的zxid。这样做的好处是可以避免Leader服务器检查Proposal的提交和丢弃工作。
数据恢复
Zab如何数据同步
完成Leader选举后,在正式开始工作之前(接收事务请求,然后提出新的Proposal),Leader服务器会首先确认事务日 志中的所有的Proposal 是否已经被集群中过半的服务器Commit
Leader服务器需要确保所有的Follower服务器能够接收到每一条事务的Proposal,并且能将所有已经提交的事务Proposal 应用到内存数据中。等到Follower将所有尚未同步的事务Proposal都从Leader服务器上同步过,并且应用到内存数据中以后, Leader才会把该Follower加入到真正可用的Follower列表中
CAP理论
CAP理论告诉我们,一个分布式系统不可能同时满足以下三种
一致性(C:Consistency)
可用性(A:Available
分区容错性(P:Partition Tolerance)
这三个基本需求,最多只能同时满足其中的两项,因为P是必须的,因此往往选择就在CP或者AP中。
一致性(C:Consistency)
在分布式环境中,一致性是指数据在多个副本之间是否能够保持数据一致的特性。在一致性的需求下,当一个系统在数
据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
可用性(A:Available)
可用性是指系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果
分区容错性(P:Partition Tolerance)
分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
ZooKeeper保证的是CP
ZooKeeper不能保证每次服务请求的可用性。(注:在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要 重新请求才能获得结果)。所以说,ZooKeeper不能保证服务可用性。
进行Leader选举时集群都是不可用
源码详解
参考百度云资料
链接: https://pan.baidu.com/s/1mLb-gzOHNGQH5TKOL8xKlw 提取码: q5aw 复制这段内容后打开百度网盘手机App,操作更方便哦
0 条评论
下一页