Raft选举机制解析

前言

Etcd是一个强一致性的分布式架构,即CP,所有请求必须经过leader节点,先由leader节点向follower节点发送日志同步消息,经过二阶段提交最终将数据应用到状态机。因此集群在初始化时必须有个选主的过程。

 

Etcd节点有以下三种角色:

 

Follower

集群初始化时,都是follower节点,follower节点负责以下几个功能:

  • 接收leader节点的日志同步请求。
  • 接收竞选节点的投票请求。

 

Candidate

每个follower节点都有一个超时时间,当过了这个超时时间一直没有收到leader节点的心跳,则会成为竞选节点,向其他节点发起投票请求。

 

Leader

所有的读写请求都需要经过leader节点,当竞选节点竞选成功后,会将角色置为leader,follower节点会从该节点同步最新的日志,以保证整个集群的一致性。

 

选举流程

  1. 节点超过超时时间,进入竞选状态,会向其他节点发起投票请求。

  2. follower节点收到投票请求后会根据投票规则决定是否投票,并将投票结果(赞成/反对)返回给竞选节点。

  3. 竞选节点收到投票反馈后,会统计投票,如果有过半节点同意则变为leader,并告知其他节点,否则重新变为Follower角色。

 

投票规则

竞选节点发起投票请求时,会向所有follower节点发送自己日志的任期和索引号, follower节点收到后会比较自己的日志是否比竞选节点的新,先比较任期,任期大的的日志最新,如果任期一样,则比较索引号,索引号大的日志最新

 

预选举

raft算法中,竞选节点在选举之前会先把自己的任期加1,然后发起投票请求,那如果此时出现了网络分区,如下图所示:

 

 

当Follower_2在达到electionTimeout后还没收到leader的心跳,会触发选举,并转为Candidate。每次发起选举时,会把Term加1。由于网络隔离,它既不会被选成Leader,也不会收到Leader的消息,而是会一直不断地发起选举。Term会不断增大,这会产生什么问题呢?

 

在网络恢复之后,因为Follower_2还是处于竞选中,它这会把它的Term传播到集群的其他节点,其他节点认为自己的日志比它旧,就肯定会选它为leader,,但事实上Follower_2节点的日志可能会落后其他节点很多了,显然是不应该成为leader节点的。那如何避免这种情况发生呢?

 

raft算法对竞选机制进行了改良,就是所谓的预选举。Candidate首先要确认自己要能赢得集群中大多数节点的投票,这样才会把自己的term增加,然后发起正式的投票,如果预选举不通过,则该节点的term不会增加。关键逻辑如下:

 

// becomePreCandidate()方法
func (r *raft) becomePreCandidate() {
    if r.state == StateLeader {
        panic("invalid transition [leader -> pre-candidate]")
    }
    r.step = stepCandidate
    r.prs.ResetVotes()
    r.tick = r.tickElection
    r.lead = None
    r.state = StatePreCandidate
    r.logger.Infof("%x became pre-candidate at term %d", r.id, r.Term)
}


//becomeCandidate()方法
func (r *raft) becomeCandidate() {
    // TODO(xiangli) remove the panic when the raft implementation is stable
    if r.state == StateLeader {
        panic("invalid transition [leader -> candidate]")
    }
    r.step = stepCandidate
    r.reset(r.Term + 1)    //一旦变为竞选角色,term立马加1
    r.tick = r.tickElection
    r.Vote = r.id
    r.state = StateCandidate
    r.logger.Infof("%x became candidate at term %d", r.id, r.Term)
}
View Code

 

可以看到预选举时Term并不会增加,而是等进入正式选举时Term才会增加。

 

posted @ 2021-09-23 17:00  独揽风月  阅读(1392)  评论(1编辑  收藏  举报