Zookeeper 基于 ZAB(Zookeeper Atomic Broadcast), 实现了主备模式下的系统架构, 保持集群中各个副本之间的数据一致性.
ZAB 协议定义了选举 (election), 发现(discovery), 同步(sync), 广播(Broadcast) 四个阶段.
选举 (election) 是选出哪台为主机; 发现 (discovery), 同步(sync) 当主选出后, 要做的恢复数据的阶段;
广播 (Broadcast) 当主机和从选出并同步好数据后, 正常的主写同步从写数据的阶段.
下面简单地介绍下 ZAB 协议, 目的是能够快速了解其精髓, 快速掌握 ZAB 协议. 然后通过论文了解具体协议的细节. 主要介绍选举和广播两个阶段.
基本概念
我们了解下 zk 的一些基本概念.
zk 集群有三种角色:
leader 就是我们说的主;
follower 就是我们说的从;
observer 可以认为是主的 clone copy, 不参与投票, 本文可忽略;
zk 集群的一个节点, 有三种状态:
looking 选举状态, 当前群龙无首;
leading leader 才有的状态;
following follower 才有的状态;
每次写成功的消息, 都有一个全局唯一的标识, 叫 zxid. 是 64bit 的正整数, 高 32 为叫 epoch 表示选举纪元, 低 32 位是自增的 id, 每写一次加一. 可以想象为中国古代的年号, 例如万历十五年, 万历是 epoch, 十五年是 id.
zk 集群一般都是奇数个机器(2n+1), 只有一个主机 leader, 其余都是从机 follower. 选主还是写数据, 要有>=n+1 台选举相同, 才能执行选举的操作.
投票优先级: 优先比较 zxid, 如果相等, 再比较机器的 id, 都按从大到小的顺序.
选举
当集群新建, 或者主机死机, 或者主机与一半或以上的从机失去联系后, 都会触发选择新的主机操作. 有两种算法 fast paxos 和 basic paxos.
fast paxos
默认 ZAB 采用的算法是 fast paxos 算法.
每次选举都要把选举轮数加一, 类似于 zxid 里的 epoch 字段, 防止不同轮次的选举互相干扰.
每个进入 looking 状态的节点, 最开始投票给自己, 然后把投票消息发给其它机器. 内容为<第几轮投票, 被投节点的 zxid, 被投节点的编号>.
其他 looking 状态的节点收到后,
1 首先判断票是否有效. 是否有效的方法为看票的投票轮数和本地记载的投票轮数是否相等:
2.1 如果比本地投票轮数的小, 丢弃.
2.2 如果比本地投票轮数的大
证明自己投票过期了, 清空本地投票信息,
更新投票轮数和结果为收到的内容.
通知其他所有节点新的投票方案.
2.3 如果和本地投票轮数相等, 按照投票的优先级比较收到的选票和自己投出去的选票.
2.3.1 如果收到的优先级大, 更新自己的投票为对方发过来投票方案, 把投票发出去.
2.3.2 如果收到的优先级小, 则忽略该投票.
2.3.3 如果收到的优先级相等, 则更新对应节点的投票.
3 每收集到一个投票后, 查看已经收到的投票结果记录列表, 看是否有节点能够达到一半以上的投票数. 如果有达到, 则终止投票, 宣布选举结束, 更新自身状态. 然后进行发现和同步阶段. 否则继续收集投票.
basic paxos
1 每个 looking 节点先发出请求, 询问其他节点的投票.
其他节点返回自己的投票 <zk 的 id,zxid>. 第一次都投自己.
2 收到结果后, 如果收到的投票比自己投票的 zxid 大, 更新自己的投票.
3 当收到所有节点返回后, 统计投票, 有一个节点的选举达到一半以上, 则选举成功. 否则继续开始下一轮询问, 直到选择出 leader 结束.
basic paxos 和 fast paxos 区别
这里 fast 是主动推送出, 只要结果有更新, 就马上同步给其他节点. 其他节点可能还没把自己的票通知给所有节点, 就发现自己投的票优先级低, 要更新投票, 然后更新再重新通知给所有节点.
basic 则要每一节点都询问完, 才能知道新结果, 然后再去问其他节点新的选举结果.
fast 比 basic 快的地方, 是一个节点, 不用和每个节点都交换投票信息后, 才能知道自己的票是否要更新. 会减少交互次数.
广播 -- 主从同步
主从同步数据比较简单, 当有写操作时, 如果是从机接收, 会转到主机. 做一次转发, 保证写都是在主机上进行.
主先提议事务, 收到过半回复后, 再发提交. 主收到写操作时, 先本地生成事务为事务生成 zxid, 然后发给所有 follower 节点. 当 follower 收到事务时, 先把提议事务的日志写到本地磁盘, 成功后返回给 leader. leader 收到过半反馈后对事务提交. 再通知所有的 follower 提交事务, follower 收到后也提交事务, 提交后就可以对客户端进行分发了.
总结
通过只有主控制写然后同步从, 保证了生成全局 zxid 不冲突. 全局唯一的 zxid 能够给选举和同步数据区分出优先级. 选举主部分了解 fast paxos 原理即可. 核心思想是递增的 zxid 顺序, 保证了能够有优先级最高的节点当主. 主从同步通过提议和提交两个阶段, 有超过一半的节点写成功, 则认为数据写成功.
来源: https://www.cnblogs.com/owenandhisfriends/p/9622208.html