Zookeeper中的事务都有一个全局唯一的ID成为ZXID,ZXID由两部分组成:一部分为leader周期epoch,另一部分为递增计数器。
(/ZXID是一个长度64位的数字,其中低 32 位可以看作是一个简单的递增计数器,针对客户端的每一个事务请求,Leader 都会产生一个新的事务 Proposal 并对该计数器进行 + 1 操作。高32位是leader周期的epoch编号,每当选举出一个新的leader时,新的leader就从本地事物日志中取出最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值,然后再对这个值+1,再将低32位的全部设置为0。高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代Leader 中事务的唯一性,这样就保证了每次新选举的leader后,保证了ZXID的唯一性而且是保证递增的。同时,也能让 Follower 通过高 32 位识别不同的 Leader,简化了数据恢复流程。基于这样的策略:当 Follower 链接上 Leader 之后,Leader 服务器会根据自己服务器上最后被提交的 ZXID 和 Follower 上的 ZXID 进行比对,比对结果要么回滚,要么和 Leader 同步。/)
从算法的角度描述数据同步的过程:
1.对于准leader,集群中的所有follower向准leader发送一个自己最后接受的事务的epoch值。
2.然后当准leader收到集群中过半的follower发送的epoch值之后,在其中选出最大的epoch值,称其为e值,并加1得到e1,并将这个e1发给集群中所有的follower。
3.当follower收到准leader发送的epoch值后,与自己的epoch值比较,若小于,则将自己的epoch值更新为e1,并向准leader发送ACK消息,同时携带epoch值和历史事务集合。
4.当准leader收到所有的follower历史事务集合后,会选择其中的一个历史事务集合作为初始化事务集合,该历史事务集合满足其ZXID最大。
正式同步过程:
1.然后就开始正式同步了,准leader会将epoch值与初始化事务集合发给集群中所有的follower。
2.当follower收到后,会接受初始化事务集合里的每一个事务,并执行,随后反馈给准leader表明自己已处理。
3.准leader收到来自过半的follower的反馈后,就会向所有的follower发送commit消息,follower收到commit后提交事务,完成数据同步。
注意:在Zookeeper选举中,通过投票(内部投票与外部投票)。同步过程与上相似,但是会简单一些,因为选举得到的leader就是zxid最大的机器若zxid一致则选取的是myid最大的机器。
来源:oschina
链接:https://my.oschina.net/u/4480939/blog/3207683