• Raft详解分析


    1、投票部分

    一个candidate向所有其他的server发送RequesetVote RPC(具体格式见论文),每次从RPC的reply中累加voteCount,如果超过一半,这个candidate变成leader,把这个消息放到channel中,反之选举失败,变成follower对应go 代码为:

    if ok { //获取投票结果
    if reply.VOTEGRANTED {
    rf.mu.Lock()
    rf.voteCount = rf.voteCount + 1
    // println("rf.me: " + strconv.Itoa(rf.me) + " voteFrom: " + strconv.Itoa(server) + " voteCount: " + strconv.Itoa(rf.voteCount))
    rf.mu.Unlock()
    if rf.state == "candidate" && rf.voteCount > len(rf.peers)/2 {
    rf.BecomeLeaderCH <- true
    }
    } else if reply.TERM > rf.CurrentTerm {
    rf.mu.Lock()
    rf.CurrentTerm = reply.TERM
    rf.state = "follower"
    rf.mu.Unlock()
    // println(strconv.Itoa(server) + " reject " + strconv.Itoa(rf.me) + " and " + strconv.Itoa(rf.me) + " step down as follower")

    如何处理放到channel中的选举结果呢?首先从channel中取出结果,如果是leader表示自己当选,修改自己状态为leader,把每个follower的nextIndex设置为当前leader的最后一个log的index(参见Raft论文),发送AppendEntries heartbeat 如果选举失败,则变成follower

    func (rf *Raft) CandidateState() {
    .......
    select { 
    case <-rf.heartbeatCH://已经有人当上leader,选举失败
    println("no longer panic, back to follower")
    rf.state = "follower"
    return
    case becomeLeader := <-rf.BecomeLeaderCH: //选举成功
    if becomeLeader { 
    rf.state = "leader"
    rf.mu.Lock()
    rf.NextIndex = []int{}
    for i:=0; i < len(rf.peers); i++ {
    rf.nextIndex = append(rf.nextIndex, len(rf.logs)-1) //把每个server 的nextIndex设置为最后一个元素
    }
    rf.mu.Unlock()
    go rf.BroadcastAppendEntriesRPC()
    return
    }

    default:
    return  //多个竞争,大家都没有当上leader,则返回,在外部循环中重新设置各个candidate定时器,再次选举
    }
    }

  • 相关阅读:
    SQLServer 时间差运算
    phpStudy
    解决Apache/PHP无法启动的问题
    apche的主配置文件)
    知识总结
    学完了js的知识,一起分享总结知识点
    JS的学习体会与分享
    SpringBoot -- pom.xml文件
    c++基本知识点
    c语言基本常识5
  • 原文地址:https://www.cnblogs.com/yanchengwang/p/5913714.html
Copyright © 2020-2023  润新知