nacos作为配置中心--选举机制

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

nacos作为配置中⼼--选举机制
通过前两篇⽂章⼤家也看出nacos从使⽤⾓度来说功能强⼤,我们现有的配置⽀持较友好,对项⽬的侵⼊性较⼩。

这也是我继续研究他的动⼒,看看到底是否能引⼊到项⽬中来。

下⾯三个主题是我接下来研究的主要⽅向:
选举机制
数据同步机制
性能
nacos作为配置中⼼的功能是基于raft协议来实现的。

为什么要选raft呢?
答案只有两个字:简单。

相⽐paxos协议来说,raft协议要简单的多。

我们⽇常开发做⽅案时也应如此,简洁有效⽅案省时省⼒、易于实现、易于维护。

我们逐渐培养⾃⼰从复杂的业务中抽象出最简单直接的⽅案的能⼒,培养⾃⼰化繁为简的能⼒。

接下来不在废话,直接上raft协议中选举机制部分。

在raft中,任何时候⼀个服务器可以扮演下⾯⾓⾊之⼀:
1. Leader: 所有请求的处理者,Leader副本接受client的更新请求,本地处理后再同步⾄多个其他副本;
2. Follower: 请求的被动更新者,从Leader接受更新请求,然后写⼊本地⽇志⽂件
3. Candidate候选⼈: 如果Follower副本在⼀段时间内没有收到Leader副本的⼼跳,则判断Leader可能已经故障,此时启动选主过程,此时副本会变成Candidate状
态,直到选主结束。

4. term:这根民主社会的选举很像,每⼀届新的履职期称之为⼀届任期
看到了这⾥,⼤家觉的raft的选举过程是怎样的呢?此处可以⼼⾥默想5分钟,已检验⼀下⾃⼰做⽅案的能⼒。

然后再看下⽜⼈是怎么实现的,从对⽐中学习⼈家的思路。

在做事⼉之前要现有⾃⼰的观念和看法,先思考⼀番,先思⽽后⾏。

这样做有两个好处:
1、不会盲从,能去其缺点,学习有点;
2、能锻炼⾃⼰的做事⼉做⽅案的能⼒,能让⾃⼰更加独⽴,不依赖别⼈,成为团队的核⼼、顶梁柱。

选举过程如下:
1. 系统刚刚启动,所有节点的任期都是0,⼤家的role都是follower
2. ⼀个启动的节点第⼀个触发未检测到⼼跳超时,⾃增任期为1,并且重新计时(投票开始时间),给⾃⼰投⼀票,然后向所有的其它节点发起投票
3. 其它节点当前的任期都为0,且⽇志也没空,肯定会投票给它,⽽且这些节点因为收到了candidate的投票选举,清零⾃⼰的⼼跳空⽩等待时间,未超时前不会发起
投票,从⽽避免多重投票导致⽆效投票的可能性
4. 第⼀个发起投票的节点收到半数投票,成为leader。

2、⾃增当前任期,且开始计时(选举计时),向其它节点发起投票
3、其它节点会⽐较任期和⽇志的序号,⾄少不能⽐⾃⼰的数据旧才会投票给第⼀个发起投票的节点
4、超过半数节点投票成功,才会成为leader,否则要等待选举超时,再发起第⼆轮投票。

动态过程: https://raft.github.io/
看到这⾥⼤家是否有疑问?
个⼈的疑问:
选取出了主节点之后,从节点如何知道谁是主节点?
任期的时长改怎么设置呢?所有节点都⼀样?
从源码给⼤家解释nacos的实现过程。

raft协议的实现都在RaftCore这个类中。

Raft中有两个⼦类分被负责选举和⼼跳。

1、选举的⼊⼝
public static final long TICK_PERIOD_MS = LISECONDS.toMillis(500L);
public void init() throws Exception {
//省略其他逻辑代码
....
("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start));
GlobalExecutor.registerMasterElection(new MasterElection());
GlobalExecutor.registerHeartbeat(new HeartBeat());
("timer started: leader timeout ms: {}, heart-beat timeout ms: {}",
GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS);
}
public static void registerMasterElection(Runnable runnable) {
NAMING_TIMER_EXECUTOR.scheduleAtFixedRate(runnable, 0, TICK_PERIOD_MS, LISECONDS);
}
public static void registerHeartbeat(Runnable runnable) {
NAMING_TIMER_EXECUTOR.scheduleWithFixedDelay(runnable, 0, TICK_PERIOD_MS, LISECONDS); }
可以看出每隔500ms就会触发⼀次选举任务和⼼跳任务
2、接下来看⼀下⼼跳是如何做的
看源码“1、”处可以发现,在leaderDue (leader 任期)内是不会进⾏选举的。

只有leaderDue 到期之后才会重置leaderDue 和heartBeatDue (⼼跳检测时长),然后发送起投票。

这⾥有个细节可以关注下,在代码“3、”处有⼀个随机值,⼤家有没有想过为什么要加⼊这个随机值?
答:随机值是为了让每个节点的leaderDueMs 不同,也就是每个节点的leader 任期不⼀样,从⽽避免⼤家同时发起投票,提升选举leader 的成功率。

换⼀种说法就是,某个节点leaderDueMs 先减为0,先⾃增term ,然后后发起投票,这是该节点由于term+1⽐其他节点term 值⼤,从⽽成功成为leader 。

如果不加随机值,⼤家同时发起头票,同时term+1 这样在这⼀轮选举中就不会有leader 。

3、选举具体过程
发起头票的过程为头票发起⽅,向不包含⾃⼰的其他节点发起头票请求,其他节点接收到请求后,进⾏上述代码处“3、”处的处理,看⼀下term 是否⽐⾃⼰的term 他,⼤则投给他,然后然后将⾃⼰的term 设置为要发起头票请求的term ,重置leaderDueMs (为了避免⾃⼰再发起⼀轮头票请求)。

最后将头票结果返回给头票发起⽅。

头票发起⽅接收到头票结果,然后根据结果有半数头票的leader 成为真正的leader 。

选举到此结束。

那么问题来了,其他节点怎么知道这个头票结果呢?如果是你该以何种⽅式通知其他节点呢?
这时候其实由于其他节点都选某个节点为主,然后⾃⼰leaderDueMs 重置,不会发起选举了。

4、⼼跳过程
第⼀步和选举类似,只有heartBeatDueMs到期之后才会发起⼼跳处理。

这⾥的⼼跳处理周期远远⼩于选举的term周期。

⽽且再⼼跳处理过程中⼼跳发起⽅和接收⽅都会重置选举时间。

通过时间的延长来阻⽌各个节点发起头票请求。

上⾯代码地四处解决了某⼀节点成为leader之后,如何将这个消息通知给其他节点,答案就⾏通过⼼跳的⽅式将leader传给其他节点,其他节点接收到⼼跳请求之后,更新leader。

接收⼼跳请求的代码如下。

到此选举机制介绍完毕。

此时有我有产⽣三个新的问题:
1、follower 超时,有问题吗?
2、leader 超时,有哦问题吗?
3、脑裂问题该如何处理?
问题⼀:
follower超时,⾃⾝会重新发起选举,如果与其他节点不通,则会⼀直处于选举状态,如果超时⼀段时间后恢复,会通过选举成为新的leader或者(接收⼼跳消息完成了选举),或者成为原来leader的follower(在发去选举请求之前接收到了⼼跳消息,成为follower)。

这时候会存在两个leader,但是由于旧leader的term较⼩,发送⼼跳消息不起效果,最终被新的leader同步为follower。

该结论代验证,仅仅是分析结论
⼜产⽣新问题,有两个leader会影响配置信息的发布吗?
问题⼆:
leader超时重新选举,差⽣新的leader。

旧leader如果恢复了,也会通过⼼跳,被同步为follower。

问题三:
脑裂问题通过问题⼀和问题⼆的答案可以看出,通过时间续约和term⽐较最终旧leader被同步为follower。

相关文档
最新文档