etcd-raft 2.3.7 raft 日志复制 log replication 以及心跳Heartbeat

raft的log replication是在了leader选举之后进行的,leader的选举可以参考这篇文章etcd-raft的leader选举


raft的Heartbeat是leader在选举成功后巩固自己地位和同步信息的一种方式,日志的复制大多数情况下适合Heartbeat是同步进行的。当一个raft节点选举成为leader后,该节点周期性执行的tick函数指向了raft.tickHeartbeat,对于leader而言主要是通知follower自己还活着,与此同时leader在收到follower对Heartbeat的响应之后,又会向日志比较落后的follower发送追加日志请求,进行log replication。

由于发起heartbeat的raft节点处于leader角色,因此,被周期调用的tick将指向tickHeartbeat:

unc (r *raft) tickHeartbeat() {
    r.heartbeatElapsed++
    // ... 

    // 如果心跳计时超过了心跳包的发送间隔,就进入发送心跳包流程,并重置心跳计时
    if r.heartbeatElapsed >= r.heartbeatTimeout {
        r.heartbeatElapsed = 0 
        r.Step(pb.Message{From: r.id, Type: pb.MsgBeat})
    }   
}

func (r *raft) Step(m pb.Message) error {
    // ...

    // Step最终调用raft.step变量指向的函数
    // 现阶段当前节点处于leader状态,所以step指向stepLeader 
    r.step(r, m)
    return nil 
}

stepLeader中心跳发送代码相关执行流程如下:

func stepLeader(r *raft, m pb.Message) {
    switch m.Type {
    case pb.MsgBeat:
        // 把心跳包广播出去
        r.bcastHeartbeat()
    return
    // ...
}

// 在bcastHeartbeat中循环的把心跳包发送出去
func (r *raft) bcastHeartbeat() {
    for id := range r.prs {
        if id == r.id {
            continue
        }
        r.sendHeartbeat(id)
        r.prs[id].resume()
    }
}
func (r *raft) sendHeartbeat(to uint64) {
    // r.raftLog.committed 已经拷贝到大多数节点上的日志index
    // r.prs[to].Match拷贝到to这个节点的日志最大下标
    commit := min(r.prs[to].Match, r.raftLog.committed)
    m := pb.Message{
        To:     to,
        Type:   pb.MsgHeartbeat,
        Commit: commit,
    }
    //把心跳包发送出去
    r.send(m)
}

follower在收到心跳包之后,最终处理心跳的包的流程会通过Step->step->stepFollower:

fu
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值