欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ETCD 源码学习--Raft 协议实现的文件说明及 Raft 数据结构解析(三)

程序员文章站 2024-03-19 21:44:16
...

在 ETCD 源码学习过程,不会讲解太多的源码知识,只讲解相关的实现机制,需要关注源码细节的朋友可以自行根据文章中的提示,找到相关源码进行学习。

主要文件说明

在ETCD中,Raft协议实现的源码主要在 etcd/raft 目录下

1.raft.go  实现Raft协议的主要逻辑。

2.log.go  用于维护日志记录,其中包括两部分 log,持久化  log 和 未持久化 log 

3.log_unstable.go 用于维护未持久化 log

4.stable.go  定义存储接口协议,同时实现 MemoryStorage 存储实例

5.node.go & rawnode.go 共同实现 Raf t节点,一个 node 相当于一个 raft 节点。主要做消息转发功能,当有请求时,会调用底层 raft 协议处理,当底层 raft 处理完之后,会将消息封装,然后传递给上层模块处理。

6.tracker/inflights.go  用于维护已发送,但未得到对应节点响应的消息日志记录。

7.tracker/processs.go  用于维护单个节点状态,比如节点活跃状态、已提交的 Index、已匹配的 Index 等。

8. tracker/tracker.go  用于管理所有节点的状态。

9. quorum 目录下的文件,主要用于实现 quorum 机制(过半机制)

10. confchange 目录下的文件,是用于实现在接收的状态机配置变更时,如何实现当前节点的配置变更。

11.raftpb 目录下的文件是消息协议文件(protobuf)

Raft 协议的数据结构

type raft struct {
	id                        uint64
	Term                      uint64
	Vote                      uint64
	readStates                []ReadState
	raftLog                   *raftLog
	maxMsgSize                uint64
	maxUncommittedSize        uint64
	prs                       tracker.ProgressTracker
	state                     StateType
	isLearner                 bool
	msgs                      []pb.Message
	lead                      uint64
	leadTransferee            uint64
	pendingConfIndex          uint64
	uncommittedSize           uint64
	readOnly                  *readOnly
	electionElapsed           int
	heartbeatElapsed          int
	checkQuorum               bool
	preVote                   bool
	heartbeatTimeout          int
	electionTimeout           int
	randomizedElectionTimeout int
	disableProposalForwarding bool
	tick                      func()
	step                      stepFunc
	logger                    Logger
}

1.节点状态参数

id:当前节点 ID

Term:当前节点任期

Vote:当前节点的选票(投给了谁做我 Leader )

state:节点状态 (Leader/Follower/Candidate/...)

lead:Leader ID

2.计时器参数

electionTimeout:选举超时时间。

randomizedElectionTimeout:随机选举超时时间,每个节点的选举超时时间不同, randomizedElectionTimeout = electionElapsed+随机数。具体计算参考 resetRandomizedElectionTimeout() 函数。

electionElapsed:选举计数器 ,在 Follower/Candidate 中,如果在 electionElapsed >= randomizedElectionTimeout, 会发起一轮选举。如果在 Leader 状态,那么当 electionElapsed > electionTimeout,Leader 会发起一次自我检查,主要目的是判断自身是否能继续维持 Leader 状态,如果不能,切换成 Follower,并发起一轮选举。

heartbeatElapsed:心跳计数器,在 Leader 节点运行,Leader 节点会定时向 Follower 发生心跳包,Follower 收到 心跳包会重置 electionElapsed,避免 Follower 发起选举。

heartbeatTimeout:心跳超时时间  当 heartbeatElapsed > heartbeatTimeout,向所有 Follower 发送心跳包

tick:逻辑计数器推进函数, 当 Leader状态时 为 tickHeartbeat。其他状态为 tickElection。

3.网络分区处理

CheckQuorum:当为 true 时, electionElapsed > electionTimeout,Leader 会进行自我检查,判断是否能继续维持 Leader 状态,如果发现连接到的节点数没有超过半数,则主动切换成 Follower,这样在网络分区中,旧的 Leader 节点可以很快指定自己过期,减少 client 连接 Leader 节点的等待时间

preVote:当为true时,选举过程会多一个预选举过程,同时会多一个 preCandidate 状态。主要作用是在正式发起选举之前,判断是否有超过半数的节点能参与选举。如果没有,放弃发起选举,这样在网络分区的情况下,可以避免脑裂问题。

4.raft协议 消息处理函数 step,主要用于处理raft的各种消息,其中包括三种模式

stepLeader: 当节点状态为 Leader 时,step 设置为该函数 (becomeLeader)

stepFollower:当节点状态为 Follower 时,step 设置为该函数 (becomeFollower)

stepCandidate:当节点状态为 Candidate 时,step 设置为该函数 (becomeCandidate)

5.集群节点状态维护

prs:该参数会维护集群中所有节点的信息,主要包括节点的活跃状态,日志复制情况等。

6.消息日志

raftLog:维护本地节点的消息日志,其中包括两个部分,一是已持久化(stable)的日志,二是未持久化(unstable)的数据

msgs:缓冲待发送给其他节点的消息日志。

在Leader节点中,会将日志消息先保存到 raftLog 中(unstable),然后 raft 会将 raftLog 中的日志,根据 prs 记录的日志同步情况,将未同步的数据,同步到对应的节点(发送到 msgs 中缓存)。

 

PS:欢迎纠正

相关标签: etcd raft etcd