当前位置:网站首页>ETCD数据库源码分析——从raftNode的start函数说起
ETCD数据库源码分析——从raftNode的start函数说起
2022-07-07 01:39:00 【肥叔菌】
如上图所示,raftNode是真正操纵ETCD RAFT API的模块,充当etcd-raft模块与上层模块之间交互的桥梁,其定义了如下成员。其中msgSnapC通道用于接收和发送快照、applyc通道用于发送待应用的Entry记录、readStateC用于向上层模块发送ReadState、ticker用于向raft模块发送定时脉冲tick、td用于检测发往同一节点的两次心跳消息是否超时。raftNodeConfig后续再说,该篇主要说明ticker模块。
type raftNode struct {
lg *zap.Logger
tickMu *sync.Mutex
raftNodeConfig
msgSnapC chan raftpb.Message // a chan to send/receive snapshot
applyc chan toApply // a chan to send out apply
readStateC chan raft.ReadState // a chan to send out readState
ticker *time.Ticker // utility
td *contention.TimeoutDetector // contention detectors for raft heartbeat message
stopped chan struct{
}
done chan struct{
}
}
初始化raftNode结构体的函数是newRaftNode,raftNodeConfig包含了已经初始化的网络transport、预写日志Storage、raftStorage以及最重要的raft模块,这些模块提供相应的接口给raftnode使用以协助完成raft log发送、持久化、多数复制等功能。
func newRaftNode(cfg raftNodeConfig) *raftNode {
raft.SetLogger(lg) // 初始化logger(略)
r := &raftNode{
lg: cfg.lg, tickMu: new(sync.Mutex),
raftNodeConfig: cfg, td: contention.NewTimeoutDetector(2 * cfg.heartbeat), // set up contention detectors for raft heartbeat message. expect to send a heartbeat within 2 heartbeat intervals.
readStateC: make(chan raft.ReadState, 1),
msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap),
applyc: make(chan toApply),
stopped: make(chan struct{
}), done: make(chan struct{
}),
}
// 这里是重点
if r.heartbeat == 0 {
r.ticker = &time.Ticker{
} // 如果heartbeat为零,则使用默认&time.Ticker{}
} else {
r.ticker = time.NewTicker(r.heartbeat) } // 否则,需要设定时间间隔为r.heartbeat
return r
}
start函数会启动一个协程运行主要的业务逻辑,这里我们会看到如果定时器超时时,select会检测到该通道,调用raftNode接口的tick函数。该tick函数会获取tickMu锁,然后调用Node接口提供的Tick函数,也就是图中的raft.Node提供的Tick函数。
func (r *raftNode) start(rh *raftReadyHandler) {
internalTimeout := time.Second
go func() {
defer r.onStop()
islead := false
for {
select {
case <-r.ticker.C:
r.tick()
// raft.Node does not have locks in Raft package
func (r *raftNode) tick() {
r.tickMu.Lock()
r.Tick()
r.tickMu.Unlock()
}
raft.Node提供的Tick函数会向n.tickc通道中写入struct{}{},而在raft.Node中会有协程执行run函数,如图中raft.Node的run协程所示,其会执行监听n.tickc通道的代码,然后执行n.rn.Tick()
。而这里n.rn.Tick()
执行的是rawnode所包含成员raft结构体的Tick成员函数,该函数会根据raft角色执行不同的tick函数:tickElection或tickHeartbeat。
// Tick advances the internal logical clock by a single tick.
func (rn *RawNode) Tick() {
rn.raft.tick()
}
边栏推荐
- JMeter function assistant - random value, random string, fixed value random extraction
- C. colonne Swapping [tri + Simulation]
- 360织语发布7.0新品 为党政军、央国企打造专属“统一数字工作空间”
- Detailed explanation of platform device driver architecture in driver development
- cf:C. Column Swapping【排序 + 模擬】
- SAP Spartacus checkout 流程的扩展(extend)实现介绍
- 老板总问我进展,是不信任我吗?(你觉得呢)
- 【FPGA教程案例13】基于vivado核的CIC滤波器设计与实现
- JVM命令之 jstack:打印JVM中线程快照
- Sequential storage of stacks
猜你喜欢
A freshman's summary of an ordinary student [I don't know whether we are stupid or crazy, but I know to run forward all the way]
postgresql 数据库 timescaledb 函数time_bucket_gapfill()报错解决及更换 license
CTFshow--常用姿势
开发者别错过!飞桨黑客马拉松第三期链桨赛道报名开启
Three updates to build applications for different types of devices | 2022 i/o key review
Dc-7 target
go-microservice-simple(2) go-Probuffer
深度聚类:将深度表示学习和聚类联合优化
PowerPivot - DAX (function)
Rk3399 platform development series explanation (WiFi) 5.52. Introduction to WiFi framework composition
随机推荐
Ctfshow-- common posture
How to keep accounts of expenses in life
可极大提升编程思想与能力的书有哪些?
PTA ladder game exercise set l2-004 search tree judgment
Peripheral driver library development notes 43: GPIO simulation SPI driver
老板总问我进展,是不信任我吗?(你觉得呢)
The solution of a simple algebraic problem
【GNN】图解GNN: A gentle introduction(含视频)
从“跑分神器”到数据平台,鲁大师开启演进之路
骑士战胜魔王(背包&dp)
Value range of various datetimes in SQL Server 2008
Convert numbers to string strings (to_string()) convert strings to int sharp tools stoi();
[Shell]常用shell命令及测试判断语句总结
[SQL practice] a SQL statistics of epidemic distribution across the country
rt-thread 中对 hardfault 的处理
cf:C. Column Swapping【排序 + 模擬】
对称的二叉树【树的遍历】
CTFshow--常用姿势
软件测试的几个关键步骤,你需要知道
如何在Touch Designer 2022版中设置解决Leap Motion不识别的问题?