简介
ZAB协议是 zookeeper atomic broadcast(zookeeper原子广播)
zookeeper是通过ZAB协议来保证分布式事务的最终一致性。
- zab协议是为分布式协调服务zookeeper专门设计的一种 支持崩溃恢复 的 原子广播协议,是zookeeper保证数据一致性的核心算法。zab借鉴了paxos算法,但又不像paxos那样,是一种通用的分布式一致性算法。它是为zookeeper设计的支持崩溃恢复得原子广播协议。
- 在zookeeper中主要依赖zab协议来实现数据一致性,基于该协议,zk实现了一种主备模型(即leader,follower模型)的系统架构来保证集群中各个副本之间数据的一致性, 这里的主备系统架构模型,就是指只有一台客户端(leader)负责处理外部的写事务请求,然后leader客户端将数据同步到其他follower节点
zab协议原理
- 发现:要求zookeeper集群必须选举出一个leader进程,同时leader会维护一个follower可用客户端列表。将来客户端可以和这些follower节点进行通信。
- 同步:leader要负责将本身的数据与follower完成同步做到多副本存储。这样也是体现了CAP中的高可用和分区容错。Follower将队列中未处理完的请求 消费完成后,写入本地事务日志中。
- 广播:leader可以接受客户端新的事务proposal请求,将新的proposal请求广播给所有的follower
================================================================================
消息广播
zookeeper客户端会随机的连接到zookeeper集群中的一个节点,如果是读请求,就直接从当前节点中读取数据;如果是写请求,那么节点就会向leader提交事务,leader接收到事务提交,会广播该事务(复制数据到follower),只要超过半数节点将复制的数据 写入成功 并成功 Ack,该事务就会被提交,同时自己也提交(leader服务器与每一个follower服务器之间都维护了一个单独的FIFO的消息队列进行 收发消息 ,将事务写入本地,来避免同步,实现异步解耦)
在整个消息广播中,leader会将每一个事务请求转换成对应的proposal进行广播,并且在广播事务proposal之前,leader服务器会首先为这个事务proposal分配一个全局单递增的唯一zxid,称之为事务id,由于zab协议需要保证每一个消息的严格顺序关系,因此必须将每一个proposal按照zxid顺序进行排序和处理。
================================================================================
崩溃恢复
zab协议的原则:
- zab协议需要确保那些已经在leader服务器上提交(commit)的事务 最终被所有的服务器提交
- zab协议需要确保 丢弃那些只在leader上被提出而没有提交的事务
简短一句话就是:提交leader已经commit过的,放弃leader 还没有commit过的proposal【这个我就比较郁闷了,因为在leader和follower之间有FIFO的消息队列进行 事务操作,实现了异步,那就会导致各个follower上执行的结果不一致啊,是不是没有执行完的事务 ,如果按照zab的原则来讲 提交所有leader所提交的事务 那又怎么会出现zxid不一致呢??毕竟选举是根据zxid大小进行选举的 ——唯一的真相可能是zab的广播原则吧,只要有过半的follower成功的ack,leader和follower便会提交该proposal】
然后根据zxid进行选举leader,选举出的leader,他的epoch会在上一任的leader的epoch的基础上自增1,并且zxid会重置。
================================================================================
数据同步
zab 如何数据同步
- 完成leader选举后(新的leader具有最高的zxid),在正式开始工作之前(接受事务请求,然后提出新的proposal),leader服务器会首先确认事务日志中的所有的proposal是否已经被集群中过半的服务器commit。这个也是为了保证数据一致性,即使集群再次崩溃也没事。------->避免从小到大选举
leader服务器需要确保所有的follower服务器能够接收到每一条事务的proposal,并且能将所有 已经提交的事务proposal应用到内存数据中。等到follower将所有尚未同步的事务proposal都从leader服务器上同步过来后,leader才会将follower加入到真正可用的follower列表中。【leader 有一个可用的follower的列表管理】
zxid是一个64位的数字,其中
- 低32位可以看作是一个简单的递增计数器,针对客户端的每一个事务请求,leader都会产生一个新的事物proposal并对该计数器进行+1的操作,
- 而高32位则代表了leader服务器上取出本地日志中最大事务proposal的zxid,并从该zxid种解析出对应的epoch值,然后对这个epoch值+1。
- 高32位代表了每代leader的唯一性,低32代表每代leader中事务的唯一性:基于这样的策略,在follower连接上leader后,leader服务器会根据自己服务器上最后提交的zxid和follower上的zxid进行对比,比对结果要么回滚,要么和leader同步
================================================================================
总结
这个zab就是一个过半即成功,zab协议让zk集群在两种模式之间转换 消息广播 和 崩溃恢复
过半原则的消息广播 崩溃恢复根据基于事务的zxid的唯一性来保证数据的唯一性
而且leader与follower之间有一个FIFO消息队列(FIFO:先进先出)解决了同步阻塞的情况
选举原则:
- 若epoch相等,选zxid最大的
- 若epoch和zxid相等,就选择server_id最大的(zoo.fcg中的myid)