没什么,搞不明白别打我就行,初学者如有问题请及时指正!
在上一篇文章我们有介绍3种server角色:Leader、Follower以及Observer(不参加选举),所以只有Leader和Follower会参加选举,那么都什么时候会出发选举呢?
- 服务器初始化启动
- 服务运行期间无法和leader保持连接
一、选举流程
假设集群中有5个服务器
选举过程分为两种:
1.全新集群选举
a.server1 启动
触发一次选举,server1投给自己一票,但是总共5台服务器未达到半数3台,所以选举无法完成。
投票结果:server1 :1票
状态:server1:LOOKING
b.server2 启动
触发选举,server1和2分别投自己一票,但是server1发现2的id比自己大,就更改选票投给server2,此时未达半数,还是LOOKING状态
投票结果:server1 :0票 server2 :2票
状态:server1:LOOKING server2:LOOKING
c.server3启动
触发选举,server1和2和3分别投自己一票,但是server1和2发现3的id比自己大,就更改选票投给server3,此时达半数投票,server3当选 leader
投票结果:server1 :0票 server1 :0票 server3 :3票
状态:server1:FOLLOWER server2:FOLLOWER server3:LEADER
d.server4启动
触发选举,server1、2、3已经不是LOOKING,不会更改选票信息,只会交换选票信息
投票结果:server1 :0票 server1 :0票 server3 :3票 server4 :1票
状态:server1:FOLLOWER server2:FOLLOWER server3:LEADER server4:FOLLOWER
e.server5启动
和server4一样投票给自己,但是已经有leader了就结束选举
投票结果:server1 :0票 server1 :0票 server3 :3票 server4 :1票 server5 :1票
状态:server1:FOLLOWER server2:FOLLOWER server3:LEADER server4:FOLLOWER server5:FOLLOWER
总结:服务器3选为leader,其余是follower,一般集群中间的机器当选leader
2.非全新集群选举
- 统计逻辑时钟是否相同,逻辑始终小说明中途可能出现宕机问题,因此数据不完成,那么该选举结果被忽略,重新投票选举
- 统一逻辑时钟后,对比数据id值 (反映数据新旧程度),数据id大的胜出
- 如果逻辑时钟和数据id都相同,那么比较服务器id,大的胜出
总结:择优选取,保证leader是zk集群中数据最完整、最可靠的一台服务器。
二、核心概念
- 服务器id:serviceid–sid 每台服务器都有自己的编号比如说1、2、3.编号越大再选择算法中权重越大
- 逻辑时钟 epoch 投票的次数,同一轮投票的过程中epoch值都是相同,每投完一次数据增加
- 事务id:zxid 事务提议Proposal生成一个全局单调唯一递增的ID,值越大数据越新,在选举算法中权重越大。
三、ZAB协议
zab协议是为zk专门设计的一种支持崩溃恢复的原子广播协议,zk依赖zab实现分布式数据一致性,来保证住呗模式的系统架构中各个副本之间的数据一致性。
zab协议包括两个模式:崩溃回复和消息广播
崩溃恢复(新选举leader)
- 服务器启动集群新建时
- 主机与当前集群一半以上的机器失去联系后
所有节点都会使用
崩溃恢复协议
来使彼此达到一个一致的状态,崩溃恢复过程需要确保那些已经在Leader上提交的事务最终被所有的事务提交。
假设两种情况:
第一种:事务A在leader上面已经被提交了,并且得到了半数Follower的ACK反馈,但是leader还没来的及将commit消息发给剩下的follower之间就挂掉了
针对这种情况,怎么保证所有服务器上都提交成功并且数据一致呢?崩溃恢复会重新选举的时候,选取ZXID最大的节点来确保其保留了最新的事件。
同时,
崩溃恢复过程需要确保丢弃那些只在Leader服务器上被提出的事务。
第二种:leader提交事务A后,还没来得及发送commit消息就挂了,导致其他server没有收到事务提议,这时leader故障恢复后又加入了集群,此时只有leader完成了A的提交,因此和其他server出现数据不一致情况
针对这种情况,我们需要让leader在故障恢复后能够丢弃这些只在它这个节点上提出的事务A,来确保数据一致。
总结:为了能够满足上述的两个情况,zk让Leader选举算法保证新选举出来的Leader拥有集群中最高的事务编号(ZXID最大),那么这就能够保证新选举出来的Leader具有所有已经提交的提案,此时新的Leader就会将事务日志中尚未提交的消息同步到各个server中。
原子广播/消息广播
选举出Leader服务器之后,进入消息广播模式,开始接收处理客户端的请求
保证集群中存在过半的机器能够和Leader的数据状态保持一致
集群中只有leader负责写,为了保证集群数据一致性,我们需要将leader上更新的数据同步到follower和observer中,所以当leader收到写请求后,会自动生成对应的提案并发起一轮消息广播。
执行流程:
- 接收到客户端发送的事务请求,Leader服务器为其生成对应的事务提议。
- leader为每一个follower和observer都准备一个FIFO队列,并把提议发送到队列上。
- follower收到事务提议后,都会将其以事务日志的形式写入本地磁盘,写入成功后反馈给leader一个ACK
- 当leader接收到半数以上follower节点的ACK,他就会认为大部分节点都同意提议,准备开始提交
- leader向所有节点发送事务commit请求,完成事务
为了防止网络等原因导致follower和observer处理请求的顺序不同而导致的数据不一致,也就是保证消息广播过程中消息接收和发送的顺序性,才引入了FIFO队列和zxid来解决这个问题。
1.leader为follower和observer各自分配了一个单独的FIFO队列,然后把事务提议发送到队列中,同时ZAB协议是通过TCP协议来进行网络通信,这样可以保证消息发送和接收顺序性。
2.在广播事务提议前,leader会给提议分配一个全局单调递增的唯一事务id(zxid),为了保证每个消息严格的因果关系,在处理时必须严格按照zxid先后顺序排序处理
整个过程了类似二阶段提交(2PC)协议,你会发现广播过程实际上是个简化版的2pc过程。
它将2pc中中断逻辑删除,leader只需要等过半的follower反馈ACK就可以执行事务提交。这种简化版的2pc提高了效率,但是怎么解决leader挂了而导致数据不一致问题呢 ?答案就是上面说的崩溃回复。
注:
引用文章:
https://blog.csdn.net/qq_35423154/article/details/118562992