参考
三种身份
节点初始身份都是follower状态
- follower 跟随者(初使状态)
- candidate 候选者
- leader 领导者
两个定时器
- 选举定时器
- 心跳定时器
选举过程
- 初始为follower状态,当没有收到心跳通知,则自身的超时,则切换成candidate状态
- 变成candidate状态后,向其它节点发起投票.
- 接收到的节点会回复这次投票.
- 如果本次投票得到多数赞同,则从candidate状态成为leader状态,其它的candidate切换为follower
- 然后向其它节点向起心跳维护leader与follower的关系.
- 标记本次选举届, 如第1届,每发起一次加1
- 之后所有的操作变化指令都由leader来决定
选举详细过程
- 由两个超时时钟决定着选举过程
- 首先是竞选超时
- 竞选超时是指跟随者成为候选人的时间
- 竞选超时一般是150毫秒到300毫秒之间的随机数
- 当到达竞选超时时间后,跟随者转变为候选人角色,并进入到 选举周期...
- 先为自己投一票.
- 此时候选人将发送 投票请求 给其它节点
- 如果收到请求的节点在当前选举周期中还没有投过票,则这个节点会投票给这个候选人...
- 然后这个节点重置它的选举周期时间,重新计时
- 一旦候选人获得半数以上的赞成投票,那么它将成为领导人
- 之后领导人将发送 附加日志 指令给跟随者
- 这些消息是周期性发送,也叫 心跳包(以此来保证它的领导人地位)
- 跟随者将响应 附加日志 消息
- 选举周期将一直持续直到某个跟随者没有收到心跳包并成为候选人
当leader挂了会如何, 将发起第二轮选举.
A, B, C节点, 第1届A为leader, 当A挂掉后
- 重新选举之后,节点 B 是选举周期2 时的领导人了
- 多数票赞成能保证每届只有一个领导人可以当选
- 如果同一时间有两个候选人,则会出现投票分裂的情况
得不到更多投票产生的脑裂过程
- 在同一个周期里有两个节点同时发起了竞选请求...
- 并且每个都收到了一个跟随者的投票响应
- 现在,每个候选人都有两票,并且都无法获得更多选票
- 这种情况下,两个节点将等待一轮竞选超时后重新发起竞选请求
- 节点A 在 竞选超时5 里得到了大多数选票,所以它成为了新领导人
日志复制(2pc)
- client向leader发起一个:
set 5
操作 - leader会先保存在日志,并没有提交.
- leader在提交日志之前, 会将指令同步到跟随者的节点日志中
- leader进入等待状态, 直到收到大多数节点记录成功的响应.
- 此时leader将提交日志, 然后leader通知所有follower提交日志.
- 最终集群达成一致.
日志复制详细过程
- 一旦选举出了领导者,我们需要向所有节点通知这一消息,并需要持续维持领导人地位
- 这是通过周期性的发送 附加日志 消息(心跳包)实现的
- 首先,一个客户端发送变化的数据给领导人
- 这条变更记录被添加到领导人的日志里...
- 然后在下一个心跳中将变更记录发送给跟随者
- 一旦大多数的跟随者确认了这条记录,那么这条记录就会被提交...
- 最后将响应客户端
网络分区导致脑裂
- 假如我们增加了一个分区,并将A和B分为一组,C、D和E分为一组
- 由于分区原因,系统中出现了两个不同的领导人
- 现在新加一个客户端并且试着修改两个领导人的数据
- 其中一个客户端将把节点B的值设置为"3"
- 但节点B不能同步大多数,所以他的日志记录仍为未提交
- 另一个客户端将修改 节点C 的值为"8"
- 因为可以同步大多数,所以这个操作能够成功
- 随后,我们修复了网络分区问题
- 节点B将会发现存在"更高领导人",所以将会选择"下台"(每产生一次选举, 有一个标记记录加1)
- 此时,节点A和节点B将会回滚它们未提交的记录,并同步新领导人的日志
- 最终,我们集群达成了一致
最终,我们集群达成了一致
网友评论