前文
概述
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 示例情景分析
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