ZooKeeper(二)
上篇
六. Zookeeper 分布式
🌻 【选举机制】
在Zookeeper集群刚启动的时候,所有的节点(服务器)都会进入选举状态,所有节点都会推荐自己成为leader。每一个节点都会将自己的选举信息发送给其他节点,节点之间会进行比较,经过多轮比较,最终胜出的节点会成为leader。
-
选举信息
-
节点的最大事务id
最大事务id越大,说明该节点干的事最多
-
选举编号 - myid
-
逻辑时钟值 - 确定轮数
经过一轮选举可能选不出leader,需要经过多轮选举。逻辑时钟值就是来记录比较轮数的。该值与选举规则并不相关,只用于记录轮数。
-
-
比较原则
-
先比较两个节点的最大事务id:"谁大谁赢"
-
如果事务id一致,比较myid:"谁大谁赢"
-
进行下一轮比较。
-
如果一个节点胜过一半级以上的节点,就会被选举成为leader。过半性
-
-
当一个Zookeeper集群已经选出了leader,为了集群的稳定性,无论新添的节点事务id或者myid是多少,都只能称为follower。除非leader宕机,重新选举。
-
宕机后的原leader节点重新连接上,会将他作为一个新节点称为follower。
-
如果集群中出现多个leader,这种现象称之为脑裂。脑裂产生的条件:
- 集群产生分裂(网络故障)
- 分裂出去的集群产生了选举。
预防脑裂:在Zookeeper集群中,如果存活的节点个数不足一半,则剩余的节点不选举也不对外服务(过半性)。可以理解为这些节点处于休眠状态。
-
Zookeeper中的节点个数一般是奇数个,最少是3个。(一个不是集群,两个不过半,至少3个)
-
Zookeeper会对每一任leader进行编号,这个编号称之为epochid,该id自增。一旦Zookeeper发现存在一个以上的leader,会将epchid较小的节点改成follower。
-
Zookeeper集群中的节点状态
-
voting - 选举
-
follower - 追随者
-
leader - 领导者
-
observer - 观察者
在集群中,一个节点一旦没设置为observer,那么这个节点的状态就不再改变。其及不参与选举,也不参与投票(原子广播),但是会监听选举和投票结果,然后根据结果产生对应的操作。- observer是没有选举权的follower。
一个集群中,会将90%~97%的节点设置为observer,目的是为了提高选举和投票效率,减小网络影响。
在Zookeeper中,observer的存活与否不会影响集群对外服务。例如“假设一个集群中有21个节点,其中有一个leader,6个follower,14个observer,那么即使14个observer全部宕机,集群依然对外服务。凡是如果4个follower宕机,集群就会停止对外服务 - 过半原则是有投票权的节点。
-
七. ZAB协议
ZAB(Zookeeper Atomic Broadcast)协议是一套专门为Zookeeper设计的进行原子广播和崩溃恢复的协议。其基于2PC算法来进行设计,利用了过半性+PAxos算法进行了改进。
1. 原子广播
-
作用:保证节点之间数据的一致性,即在Zookeeper中,访问任意一个节点获取到的数据都是相同的。
-
基于2PC算法来进行设计,利用了过半性+PAxos算法进行了改进。实际过程中要么是请求提交,要么是请求中止,核心思想是一票否决
2PC - Two Phase Commit - 二阶段提交。
- 请求阶段:协调者收到请求之后不能立即决定执不执行该请求,而是发给每一个参与者,等待参与者的反馈消息。
- 提交阶段:如果协调者收到所有参与者返回的yes,那么协调者就会命令每一个参与者执行这个请求。
- 中止阶段:如果协调者没有收到所有参与者返回的yes,那么协调者就会命令所有参与者放弃这个请求。如果一段时间内没有收到某个参与者反馈,将默认为no。
2PC算法设计和实现过程相对简单,但是非常受外界环境影响,对网络环境的容错性相对较差。集群越大,失败的概率越高。
【改进之后】
- leader收到请求后,会先将这个请求记录到本地的日志文件:log.xxxx中。其存储位置由配置文件中的dataDir。如果记录失败,直接报错;如果记录成功,leader会把请求(不止一个)放到队列,发给每一个follower。
- follower收到队列之后,也会将请求队列记录到本地的日志文件log.xxxx中。如果记录成功,则认为请求可以执行,反馈leader一个yes;如果记录失败,则follower认为请求不能执行,返回No。
- 如果leader收到半数以上的yes,就会要求所有follower执行,反之会要求所有follower删除之前的记录(回滚)。
-
返回no的可能原因:(理应返回yes)
- 文件被占用——非大问题,Zookeeper会自动考虑新增
- 磁盘满了或磁盘损坏——Zookeeper解决不了。
-
如果follower记录失败,leader却要求执行这个请求,follower会给leader发请求。leader收到请求之后,会把操作放到队列中发送给follower,follower会再次试图记录日志再次执行;如果再次记录失败,又会重复发送请求。如果在维护集群的时候发现follower频繁发送请求给leader,则说明无法记录日志。
2. 崩溃恢复
在Zookeeper集群中,当leader丢失的时候,集群不会停止服务而是会选举产生一个新的leader,这个过程称之为崩溃恢复。
- 作用:保证集群的可用性,避免单点故障。
- 当一个节点重新连入集群,该节点会先找到自己的最大事务id,然后会给leader发送一个请求,leader收到请求之后会比较事务id是否一致,如果不一致,leader就会将所缺失的事务放到队列中返回给这个节点要求补齐。
- Zookeeper会对每一任的leader分配一个递增的epochid。当leader上任之后,这个leader会将自己的epochid发给每一个follower,follower收到之后会存储到本地文件acceptedEpoch中。
- 在集群中,事务id实际是由64位二进制(16位16进制)数字组成,其中高32位是Epochid,低32为是实际的事务id。(高位的0会省略)
八. 总结
Zookeeper有以下特性,分别体现在不同地方。
- 过半性——过半选举,过半服务,过半操作。
- 数据一致性——访问任意一个节点,获取的数据都是相同的。
- 原子性——一个请求到了Zookeeper上之后,要么所有节点都执行,要么都不执行。
- 可靠性——保证集群的高可用。
- 顺序性——leader按照什么顺序接受的请求,follower就会按照什么顺序执行请求。【内部传递采取队列】
- 实时性——在网络条件较好的情况下可以实时监控Zookeeper变化。