ZAB、Raft协议简述

CAP原则

1、一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值,即写操作之后的读操作,必须返回该值。(分为弱一致性、强一致性和最终一致性)
2、可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
3、分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

BASE原则

1、基本可用(BA):保证数据的可用性。任何请求都会有响应(也可能是失败)。
2、软状态(S):软状态和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据传输的过程存在延时。
3、最终一致性(E):强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性

在分布式场景中,分区容错P,一般是针对多节点部署的系统,分区指网络分区(由于网络原因节点之间无法通信同步数据),容错指系统节点出现分区了对外依然要能提供服务,不能说分区了导致整个系统不能对外提供服务了。在满足P的前提下,客户端发一条数据给服务1,因为分区发生这条数据暂时无法同步给服务2。如果要保证整个分布式系统的数据一致性C,肯定要牺牲掉可用性A,也就是整个分布式系统对外暂时不可用或者服务2不能使用,不然客户端对服务1和服务2拿到的数据结果会不一致。
同样道理,如果要保证可用性A,那肯定要牺牲掉一致性C,因为数据还没在服务间同步,客户端查询服务1和服务2的数据结果肯定不一样。

目前流行的注册中心基本都是基于CP模式或AP模式的,Zookeeper基于是CP模式,Eureka基于AP模式,Nacos有CP模式和AP模式两种。本次主要分析下Zookeeper的CP模式和Nacos的CP模式的实现原理。

  • Nacos(CP)基于Raft协议、Zookeeper是基于ZAB协议,Raft和Zab都是分布式一致性协议Paxos的简化,两者很类似,主要包含两部分
    1、leader选举:半数以上节点同意才能成为leader
    2、集群写入数据同步:两阶段提交,半数以上节点写入成功

Leader选举

zab选举

zk选举会经过两轮投票(机器1 myid=1;机器2 myid=2;选票格式vote(myid,ZXID))
1、机器1,发送自己的选票(1,0),收到的选票是(2,0),将收到的票跟自己投出去的票对比,优先选择zxid大的为leader,zxid大的机器包括的数据是最新的,如果zxid一样,默认选myid大的为leader,推荐(2,0)为leader
2、机器2,发送自己的选票(2,0),收到的选票是(1,0),将收到的票跟自己投出去的票对比,推荐(2,0)为leader
3、机器1,发送自己的选票(2,0),收到的选票是(2,0),将收到的票跟自己投出去的票对比,投一台机器的票数已经超过集群的半数,此时选举就结束了,确定(2,0)成为leader
4、机器2,发送自己的选票(2,0),收到的选票是(2,0),将收到的票跟自己投出去的票对比,确定(2,0)成为leader
ZAB、Raft协议简述_第1张图片

raft选举

1、三台机器启动时,各自循环执行任务MasterElection,生成选举时间leaderDueMs(0~15s随机数),循环一次,选举时间减去500ms,直到选举时间小于等于0,则开始发起选举;
2、若机器S1,选举时间先到0,则S1先发起选举,S1先重置自己选举时间leaderDueMs(15~20s随机数),心跳时间heartbeatDueMs(5s)
3、S1先投票给自己,并将自己选举周期Term(S1)加1,状态变为候选者CANDIDATE
4、S1将自己的选票信息发送给其他节点,S2、S3收到选票信息后进行判断,以S2为例
4.1、若收到候选节点S1的周期大于本节点的周期,则投候选节点S1为LEADER,更新自己选举周期为Term(S1),状态为FOLLOWER,并发送自己的选票
4.2、若收到候选节点S1的周期小于本节点的周期,则投自己S2为LEADER,并发送自己的选票
5、S1收到其他节点的选票结果,若超过半数以上机器投S1,则将自己更新为LEADER

ZAB、Raft协议简述_第2张图片

数据同步

zab协议

ZAB 协议的消息广播过程使用的是一个原子广播协议,类似一个 两阶段提交过程。对于客户端发送的写请求,全部由 Leader 接 收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数(含leader 自己)成功响应,则执行 commit 操作。
ZAB、Raft协议简述_第3张图片

raft协议

leader节点收到客户端请求后,先将数据写入本地磁盘,并异步写入内存;使用CountDownLatch计数器,初始值为节点数一半以上(即2); 然后遍历所有节点同步数据,若是leader节点,因为数据已经写入成功,所以countDown技术器减1;给follower节点发送同步数据请求/raft/datum/commit,follower节点收到请求后,将数据写入磁盘,并异步写入内存,然后给主节点返回处理成功ok;leader节点收到follower节点的响应,若成功则技术器减1;若半数以上机器处理成功,则技术器减为0;则await等待的主线程会恢复,即数据同步成功
ZAB、Raft协议简述_第4张图片

脑裂问题

脑裂问题通常是发生在节点间不能通信情况下,集群可能会分裂出多个leader的集群
ZK和Nacos都是通过过半数机制和选举周期来避免脑裂的

Raft协议使用过半机制和选举周期来避免脑裂
Zab协议使用过半机制和全局唯一的Zxid来避免脑裂

  • 在 ZAB协议的事务编号ZXID 设计中,ZXID 是一个 64 位的数字,其中低32 位可以看作是一个简单的递增的计数器,针对客户端的每一个事务请求,Leader都会产生一个新的事务Proposal 并对该计数器进行 + 1
    操作。 而高 32 位则代表了 Leader 服务上取出本地日志中最大事务Proposal 的 ZXID,并从该 ZXID 中解析出对应的
    epoch 值(leader 选举周期),当一轮新的选举结束后,会对这个值加一,并且事务id又从0开始自增。

如图,有三台S0、S1、S2的集群,正常情况下,S0选举成为leader;此时因为网络原因,S0和S1、S2节点之间无法进行通信,则S1、S2重新开始选举,通过半数以上机制选举出S1为leader,此时集群中出现两个leader,出现脑裂问题。
1、脑裂后写数据,两个leader都会写数据,新的leader写数据时,S1和S2都写入成功,超半数以上,则数据写入成功;但是老的leader写数据时,因为达不到半数以上要求,数据也只会写在本地文件,不会写入内存,对客户端来说不可见的,是写入不成功的。
2、数据同步,S0长时间和其他节点通信失败,则会由leader变为候选者节点,新leader的选举周期是大于老leader的,新leader拥有最新的数据,因此网络恢复后,进行数据同步时,S0会变为follower,从新leader节点S1同步最新的数据。
3、集群个数建议设为奇数,若原来是4节点的集群,脑裂后变为2个节点和2个节点的两块区域,因为过半数机制,至少要3个节点同意才会选出leader,这种情况下是选不出leader的,导致整个集群不可用。
4、若原来是5节点的集群,脑裂后变为2个节点和3个节点的两块区域,出现两个leader。因为过半数机制,2个节点的区域是写入不成功数据的;只有3个节点的集群才会写入成功数据。(过半数机制是整个集群5个节点前提下的,并不是每个分区的)
ZAB、Raft协议简述_第5张图片
ZAB、Raft协议简述_第6张图片

ZAB、Raft协议简述_第7张图片

你可能感兴趣的:(Zookeeper,Nacos注册中心,java,分布式,开发语言)