Raft算法笔记——RawNode

249 阅读2分钟

前文

概述

RawNode是TiKV/tinykv中对Raft节点的一层封装,Raft节点通过RawNode与上层交互。

Step和tick

RawNode::step和RawNode::tick分别对应raft节点的同名函数,在收到 Raft 消息之后,调用 RawNode::step 方法来处理这条消息。每隔一段时间(称为一个 tick),调用 RawNode::tick 方法使 Raft 的逻辑时钟前进一步。

HardState和SoftState

hardstate保存了Raft节点的任期、投票和已提交日志的信息,hardstate信息可以从配置信息中读取并持久化。

softstate则保存了节点的领导、节点自身的角色信息。

// NewRawNode returns a new RawNode given configuration and a list of raft peers.
func NewRawNode(config *Config) (*RawNode, error) {

	raft := newRaft(config)
	model := &RawNode{
		Raft:      raft,
		hardState: pb.HardState{Term: raft.Term, Vote: raft.Vote, Commit: raft.RaftLog.committed},
		softState: &SoftState{Lead: raft.Lead, RaftState: raft.State},
	}
	return model, nil
}

由于领导的更迭必然会导致任期的更迭,可以认为在稳定的集群中,只有hardstate变化时才会导致softstate变化,故针对hardstate的变化更能反应RawNode的更新需要不需要被上级状态机获取。

Ready、HasReady和Advance

hasReady的返回值为boolean值,用于告诉上层,该节点是否有需要更新的信息或是有需要发送的Message。

// HasReady called when RawNode user need to check if any Ready pending.
func (rn *RawNode) HasReady() bool {
	hard := pb.HardState{
		Term:   rn.Raft.Term,
		Vote:   rn.Raft.Vote,
		Commit: rn.Raft.RaftLog.committed,
	}

	if !IsEmptyHardState(hard) && !isHardStateEqual(hard, rn.hardState) {
		return true
	}

	if len(rn.Raft.RaftLog.unstableEntries()) > 0 || len(rn.Raft.RaftLog.nextEnts()) > 0 || len(rn.Raft.msgs) > 0 {
		return true
	}

	//从快照获取
        /////////


	return false
}

分别检查RawNode的Raft节点的HardState是否变化,以及该节点的RaftLog是否变化或产生新的Message。

Ready用于将RawNode的HardState、SoftState、Message、Entries一同返回给上层。

而Advance则是由上层告诉RawNode,这一Ready状态已被同步,并将其写入RawNode的软、硬状态中,使之与其含有的Raft节点的软、硬状态同步。

参考文章

TiKV 源码解析系列文章(二)raft-rs proposal 示例情景分析

Pingcap TinyKV 2022 lab2思路及文档

tikv/tikv: Distributed transactional key-value database, originally created to complement TiDB

talent-plan/tinykv: A course to build distributed key-value service based on TiKV model