Zookeeper
ZAB协议
概述
- ZAB(Zookeeper Automic Broadcast)是一套专门为Zookeeper设计的用于进行原子广播和崩溃恢复的协议
- ZAB协议主要包含了两个功能
- 原子广播:保证数据一致性
- 崩溃恢复:保证集群的高可用
- ZAB协议本身是基于2PC算法来进行的设计,加入了PAXOS算法和过半性进行了改进
- 正因为ZAB协议的特点,所以Zookeeper是一个CP框架
2PC算法
-
2PC(Two Phase Commit),二阶段提交,顾名思义,将请求的完成过程拆分成了2个阶段
-
在2PC算法中,包含了两类角色:协调者(negotiator)和参与者(participants)
-
过程
-
请求阶段:协调者收到请求之后,不会立即决定这个请求是否执行,而是会将这个请求发送给所有的参与者,要求所有的参与者在规定时间内进行反馈
-
提交阶段:当协调者在规定时间内收到所有参与者返回的yes,那么就表示这个请求可以执行,此时协调者命令所有的参与者执行这个请求
-
中止阶段:当协调者没有在规定时间内收到所有参与者的yes,那么此时协调者就会放弃这个请求并且命令所有的参与者也放弃这个请求
-
-
2PC只会执行两个阶段:请求-提交,请求-中止
-
2PC的核心思想是"一票否决"
-
2PC的优势和劣势都非常明显
- 优势:理解和实现过程都会非常简单
- 劣势:会非常受外部环境影响。当集群规模较大的时候,2PC基本不可能成功
-
2PC提供了一种思路:在分布式环境中,如何就一个请求达成所有节点的一致性
PAXOS算法
- PAXOS算法是兰伯特在1998年发表的一篇论文<PAXOS Made Simple>首次提出,后来兰伯特在2001年的时候才发表了这个算法的推论过程,并且兰伯特凭此获得了图灵奖
- 故事背景:在一个PAXOS小岛上,生活着一群人,这群人由议会管理,议会中的每一个议员都不是专职的而是兼职的,这也就意味着每一位议员都会随时参与议会提案的决策,也随时都会撤离。那么此时,如何就一项提案达成一个一致性的意见?
- PAXOS算法解决的问题:如何在不稳定网络中达成集群的一致性
- PAXOS算法中包含了3类角色
- Proposer:提议者,负责提出提案(Proposal)
- Acceptor:接受者,接收并且回应提案
- Learner:学习者,不参与决策,而是学习最后的效果
- 一个节点既可以是Proposer,也可以是Acceptor(这与zookeeper不同,zookeeper只能有一个leader)
- PAXOS算法过程
- Prepare(准备)阶段
- Proposer会先给自己的提案生成一个全局唯一且递增的编号Proposal ID,并且给Acceptor发送Propose请求。注意,此时这个请求中没有携带具体的请求内容,只是携带Proposal ID
- Acceptor接收到Proposer的请求之后,会进行Promise(承诺):
- 不再接收Proposal ID小于等于当前编号的Propose请求
- 不再接收Proposal ID小于当前提案的Accept请求
- 在不违背承诺的前提下,Acceptor回复给Proposer当前接收到的最大的Proposal ID,如果没有则返回null
- Accept(接受/表决阶段
- Proposer在接收到半数及以上的Acceptor返回的Promise之后,会要求所有的Acceptor执行刚才的提案
- Acceptor在不违背承诺的前提下,会处理这个Proposal
- Learn(学习)阶段:Proposal执行完成之后,Learner会执行这个请求
- Prepare(准备)阶段
- PAXOS算法可能会导致产生活锁
原子广播
-
原子广播,依赖于ZAB协议来实现了数据一致性。基于ZAB协议,Zookeeper实现了一种类似于主从结构的特点
-
不同于PAXOS算法的地方在于,在ZAB协议中,只允许一个角色(leader)进行提案,并且在集群中只能有一个leader(全局唯一),从而避免产生活锁问题
-
过程
- leader接收到请求之后,会先将这个请求记录到本地的日志文件中
- 如果记录成功,那么leader会为这个请求生成一个唯一的编号(事务id,Zxid),然后将Zxid放到队列中,发送给每一个follower
- follower收到队列之后,会从队列中依次取出请求,记录到本地的日志文件中。如果记录成功,那么会给leader返回一个ACK(Acknowledge Character,确认字符)表示确认;如果记录失败,那么会给leader返回一个失败信息
- 如果leader收到半数及以上的follower返回的ACK,那么就表示这个请求可以执行,那么此时leader就会命令所有的follower以及observer执行这个请求;反之,就会命令所有的follower以及observer放弃这个请求
-
日志文件的位置由
dataLogDir
属性决定,但是dataLogDir
的值默认和dataDir
一致 -
查看log文件
# 从Zookeeper3.5.5开始,提供了zkTxnLogToolkit.sh;在3.5.5之前,通过LogFormatter类来查看 zkTxnLogToolkit.sh log.200000001
-
查看快照文件
zkSnapShotToolkit.sh snapshot.100000000
-
如果follower记录失败,那么还需要执行这个请求,此时follower会给leader发送请求,请求获取刚才任务的事务id,重新记录,记录成功,则执行这个任务;如果记录失败,那么会重新请求重新记录
-
如果一个节点加入了Zookeeper,这个节点会先找到自己最大的事务id,然后自己的最大事务id发送给leader,leader收到之后,会将欠缺的事务放入队列中发送给这个follower,follower收到之后,回依次从队列中取出请求依次记录执行。这个节点在补齐期间,不对外接收写操作
-
注意:Zookeeper所有的节点都能接收请求,如果是读请求,那么直接处理回复;如果follower接收到了写请求,会将这个请求转给leader,进行原子广播
扩展
CAP理论
概述
- 对于分布式框架而言,基本上都会遵循CAP三大理论
- CAP(CAP理论是从客户端角度出发的!!!)
- C(Consistency):一致性。在一段时间内,访问这个集群获取到的数据是相同的 。注意,此时,在一个时间段内,不要求每一台服务器的数据都一样,只要保证客户端获取到的数据一样就行
- A(Availability):可用性。当客户端对集群中的节点发起请求的时候,节点能够在合理的时间内(一般理解为立刻)进行响应 - 时效性。注意,此处的可用性和服务器的高可用不是一回事儿!!!
- P(Partition Tolerance):分区容忍性。当集群中的某一个或者一部分节点产生故障的时候,不会影响集群其他功能的使用和运行。注意,服务器的高可用指的是分区容忍性
- CAP经过严格的理论证明,无法同时满足。对于集群而言,首先要考虑满足P,所以一个集群要么是CP结构要么是AP结构
一致性方式
- 强一致性:当一个节点上的数据发生变化的时候,其他节点能够立即感知这个变化并作出对应相应
- 弱一致性:当一个节点上的数据发生变化的时候,其他节点能够部分感知这个变化或者对变化没有感知
- 最终一致性:忽略中间过程,最终结果相同
一致性实现方案
- 主从(Master-Slave,简称为M/S)结构:通过一个主节点来管理其他的从节点,客户端只能通过访问主节点来获取数据
- PAXOS算法及其变种,例如ZAB协议就是PAXOS的变种算法
- WNR策略。W表示写入节点数量,R表示读取节点数量,N表示总节点数量,只要保证W+R>N,就能保证数据一致性——