Raft是干啥的?
简述如下图:用户SET 5,3个不同节点都能获取SET 5的操作。所谓的最简单的分布式一致性。
Raft项目包含哪些模块?
项目有多少行?
分析下整个项目大概是1W多行,并不是很大,代码注释非常齐全,理解起来比较轻松。代码抽象得很好,非常值得学习。
-> % cloc ./
77 text files.
77 unique files.
8 files ignored.
github.com/AlDanial/cloc v 1.90 T=0.09 s (814.1 files/s, 201614.7 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
Go 57 2207 2786 11864
Markdown 4 106 0 255
YAML 4 26 29 141
XML 4 0 0 108
make 1 10 2 33
Bourne Shell 1 3 3 10
-------------------------------------------------------------------------------
SUM: 71 2352 2820 12411
-------------------------------------------------------------------------------
从哪里开始?
首先,我们来看下api.go/Raft结构,表示的是一个Raft节点,最核心的数据结构。划分3大块
-
NewRaft节点需要的信息:下图中标红点的,几大核心组成。下一篇我们从网络层开始详细分析。
除了raftState,其他部分全是interface,模块抽象的很细致。
-
Leader操作相关:整个Raft最核心的就是Leader的状态转换过程。我们后续也会对这一部分的实现做详细说明。
-
一些异步操作:这一块是嵌入在各个模块的实现中的。项目里面一些chan的使用也是值得学习的。
新建Raft节点逻辑?
-
① 校验配置
-
② 获取当前任务,这里是从StableStore中获取
-
③ 获取最近的日志号和具体Log,从LogStore中获取
-
④ 创建Buffer applyCh,用来应用Log到FSM。这里Future的应用可以学习下,后面写applyLog的时候可以详细分析。
-
⑤ 初始化Raft结构。
-
⑥ Set各种变量,这里可以研究下config的怎么实现线程安全的变更。
-
⑦ 尝试从备份中恢复,处理peer变更日志,eg:添加节点、删除节点。这里为啥只处理Peer变更信息,都已经将Log解析出来了,为啥不直接应用呢?
-
⑧ 给传输层注册心跳处理器。在这里初始化,而不是在goroutine里面处理,是为了避免队头阻塞。