etcd中raft协议的消息(三) ——MspApp和MsgAppResp消息

MsgApp消息

        上小结我们看到节点发起选举的相关消息,当候选人通过选举成为新的Leader后,首先会调用becomeLeader方法初始化相关状态,然后会调用bcastAppend方法,该方法主要向集群中其他节点广播MsgApp消息。消息的简略流程如下:

   

becomeLeader方法的主要功能:

作用:节点赢得选举变成Leader节点
1.检测当前节点如果是Followerpanic
2.
step设置成stepLeader
3.
重置raft实例的Term、心跳计时器、选举计时器、选举超时时间等字段
4.Leader设置成当前节点的id
5.
更新当前节点的角色
6.保守地将pendingConfIndex设置为日志中的最后一个索引
7.向当前节点的raftLog中追加一条空的Entry记录
 

func (r *raft) becomeLeader() {
   // TODO(xiangli) remove the panic when the raft implementation is stable
   //检测当前节点的状态,禁止从Follower状态切换成Leader状态
   if r.state == StateFollower {
      panic("invalid transition [follower -> leader]")
   }
   //将step字段设置成stepLeader
   r.step = stepLeader
   r.reset(r.Term)       //重置raft实例的Term等字段
   r.tick = r.tickHeartbeat   //tick字段设置成tickHeartbeat方法
   r.lead = r.id        //将leader字段当前节点的id
   r.state = StateLeader     //更新当前节点的角色
   ents, err := r.raftLog.entries(r.raftLog.committed+1, noLimit)
   if err != nil {
      r.logger.Panicf("unexpected error getting uncommitted entries (%v)", err)
   }

   // Conservatively set the pendingConfIndex to the last index in the
   // log. There may or may not be a pending config change, but it's
   // safe to delay any future proposals until we commit all our
   // pending log entries, and scanning the entire tail of the log
   // could be expensive.
   /*
   保守地将pendingConfIndex设置为日志中的最后一个索引。
   可能有也可能没有挂起的配置更改,但是在我们提交所有挂起的日志条目之前延迟任何未来的提议是安全的,
   并且扫描日志的整个尾部可能很昂贵。
   */
   if len(ents) > 0 {
      r.pendingConfIndex = ents[len(ents)-1].Index
   }
   //向当前节点的raftLog中追加一条空的Entry记录
   r.appendEntry(pb.Entry{Data: nil})
   r.logger.Infof("%x became leader at term %d", r.id, r.Term)
}

bcastAppend方法

    该方法的主要作用是向集群中的其他节点发送MsgApp(或MsgSnap)消息,这里我们先忽略MsgSnap消息,后面会详细介绍。

func (r *raft) bcastAppend() {
	r.forEachProgress(func(id uint64, _ *Progress) {
		if id == r.id {
			return
		}

		r.sendAppend(id)
	})
}

    sendAppend方法的处理流程

1.获取目标节点的Progress,如果是暂停状态,则返回
2.创建待发送的消息实体m,并设置目标节点的ID
3.获取Next-1对应的记录的Term值,获取需要发送的Entries
4.上述两次raftLog查找出现异常时,就会形成MsgSnap消息,将快照数据发送到指定节点。
5.否则,发送MsgSnap类型的消息
6.发送前面创建的MsgApp或MsgSnap类型的消息,raft.send()会设置MsgApp消息的Term值,并将其追加到raft.msgs中等待发送。
func (r *raft) sendAppend(to uint64) {
	pr := r.getProgress(to)  //获取目标节点的Progress
	if pr.IsPaused() { //检测当前节点是否可以向目标节点发送消息
		return
	}
	m := pb.Message{} //创建待发送的消息
	m.To = to	//设置目标节点的ID

	term, errt := r.raftLog.term(pr.Next - 1)  //pr.Next是下个待复制Entry的索引位置,获取Next索引对应的记录的Term值
	ents, erre := r.raftLog.entries(pr.Next, r.maxMsgSize)	//获取需要发送的Entry记录(ents)

	if errt != nil || erre != nil { // 上述两次raftLog查找出现异常时,就会形成Ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值