Zookeeper高可用笔记
之前Zookeeper通过过半选举来选出主节点,如果3节点的集群,挂掉的是主节点该如何是好呢?这个问题之前没有深入学习,在此查阅资料笔记下。
ZAB
Zookeeper采用了ZAB算法来解决选举的问题。
ZAB(Zookeeper Atomic Broadcast,zookeeper原子广播),ZAB协议用来保证zookeeper各个节点之间数据的一致性。ZAB协议包括如下特点:
follower节点上所有的写请求都转发给leader
写操作严格有序
ZooKeeper使用改编的两阶段提交协议来保证各个节点的事务一致性
整个提交过程分为4个步骤:
协调者询问所有的参与者是不是可以提交了
参与者回复yes or no
协调者收到所有的yes之后执行commit否则执行rollback
参与者执行完成后回复ACK
zookeeper采用的是改编过的两阶段提交,就是在第三步的时候,不需要所有的参与者回复yes,只需要超过半数(刚好半数也不行)的参与者回复yes。之所以是超过半数而不是所有参与者回复yes,是为了避免少量的参与者出现单点故障或者网络波动导致协调者长时间收不到回复。
两种状态
zookeeper集群的状态分为两种:正常状态和异常状态。也就是有leader(能提供服务)和没有leader(进入选举)
广播模式
广播模式就是指zookeeper正常工作的模式。正常情况下,一个写入命令会经过如下步骤被执行
leader从客户端或者follower那里收到一个写请求
leader生成一个新的事务并为这个事务生成一个唯一的Zxid
leader将这个事务发送给所有的follows节点
follower节点将收到的事务请求加入到历史队列(history queue)中,并发送ack给leader
当leader收到大多数follower(超过法定数量)的ack消息,leader会发送commit请求
当follower收到commit请求时,会判断该事务的Zxid是不是比历史队列中的任何事务的Zxid都小,如果是则commit,如果不是则等待比它更小的事务的commit
恢复模式
当leader故障之后,zookeeper集群进入无主模式,此时zookeeper集群不能对外提供服务,必须选出一个新的leader完成数据一致后才能重新对外提供服务。zookeeper官方宣称集群可以在200毫秒内选出一个新leader。正常模式下的几个步骤,每个步骤都有可能因为leader故障而中断。但是恢复过程只与leader有没有commit有关。
首先看前三个步骤,只做了一件事,把事务发送出去。如果事务没有发出去,所有follower都没有收到这个事务,leader故障了。所有的follower都不知道这个事务的存在,根据心跳检测机制,follower发现leader故障,重新选出一个leader。会根据每个节点Zxid来选择,谁的Zxid最大,表示谁的数据最新,自然会被选举成新的leader。如果Zxid都一样,表示在follower故障之前,所有的follower节点数据完全一致,此时选择myid最大的节点成为新的leader,因为有一个固定的选举标准会加快选举流程。新的leader选出来之后,所有节点的数据本身就是一致的,此时就可以对外提供服务。
假设新的leader选出来之后,原来的leader又恢复了,此时原来的leader会自动成为follower,之前的事务即使重新发送给新的leader,因为新的leader已经开启了新的纪元,而原先的leader中Zxid还是旧的纪元,自然会被丢弃。并且该节点的Zxid也会更新成新的纪元。纪元的意思就是标识当前leader是第几任leader,相当于改朝换代时候的年号。
如果在leader故障之前已经commit,zookeeper依然会根据Zxid或者myid选出数据最新的那个follower作为新的leader。新leader与follower建立FIFO的队列, 先将自身有而follower缺失的事务发送给它,再将这些事务的commit命令发送给 follower,这便保证了所有的follower都保存了所有的事务、所有的follower都处理了所有的消息。
- ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。
- ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。