![]()
- SOFAJRaft 概述 -
咱们对Raft协议已经进行了原理的解析,接下去咱们从通过SOFAJRaft 框架的核心流程剖析加深对Raft协议的理解。SOFAJRaft 是一个纯 Java 的 Raft 算法实现库, 基于百度 braft 实现而来, 使用 Java 重写了所有功能, 支持:
额外扩展了一些功能:
-
对称网络分区容忍性
-
重启后的转移领袖、负载均衡场景实现
-
更丰富的指标统计展示
-
通过Jepsen一致性验证测试
-
包含嵌入式分布式KV存储实现
整体项目如下:
![]()
![]()
- 领袖选举 -
SOFAJRaft 的选举主要通过判单两个属性:LogIndex 和 Term;Term 即任期,LogIndex即提交到 raft group 中的任务都将序列化为一条日志存储下来,每条日志一个编号,在整个 raft group 内单调递增并复制到每个 raft 节点。可以理解为事务id。投票处理的逻辑主要在 com.alipay.sofa.jraft.core.NodeImpl中,主要有四个函数:
整体流程如下:
-
Candidate(候选人) 被 Election timeout触发
-
Candidate 开始尝试发起 pre-vote 预投票
-
Follower(追随者) 判断是否认可该 pre-vote request
-
Candidate 根据 pre-vote response 来决定是否发起 RequestVoteRequest
-
Follower 判断是否认可该 RequestVoteRequest
-
Candidate 根据 response 来判断自己是否当选
![]()
使用预投票可以防止网络抖动等特殊原因引起的瞬时失联节点无故捣乱:候选者在发起投票之前,先发起预投票,如果没有得到半数以上节点的反馈,则候选者就会识趣的放弃参选,也就不会抬升全局的 Term。
投票源码:
![]()
预投票源码:
![]()
![]()
- 存储机制 -
SOFAJRaft 存储模块分为:
-
Log 存储记录 Raft 配置变更和用户提交任务日志,把日志从 Leader 复制到其他节点上面;
-
Meta 存储即元信息存储记录 Raft 实现的内部状态,比如当前 term,、投票给哪个节点等信息
-
Snapshot 存储用于存放用户的状态机 Snapshot 及元信息,用于Node重启重建整个状态机实例。
![]()
LogManager 调用日志存储 LogStorage 实现逻辑:
![]()
SnapshotExecutor 状态机快照和远程安装镜像实现逻辑:
![]()
![]()
- 一致性状态机 -
通过存储的设计,在引入状态机机制,就可以完成一致性状态机。SOFAJRaft状态机组成有:
-
StateMachine:业务逻辑实现的主要接口,状态机运行在每个 raft 节点上,提交的 task 如果成功,最终都会复制应用到每个节点的状态机上。,核心是 onApply(Iterator) 方法,应用通过 Node#apply(task) 提交的日志到业务状态机。
-
FSMCaller:封装对业务 StateMachine 的状态转换的调用以及日志的写入等,一个有限状态机的实现,做必要的检查、请求合并提交和并发处理等。
SOFAJRaft Node节点利用日志复制完成数据同步,主要组成有:
![]()
- 总结 -
本文通过简单介绍了下SOFAJRaft的选举实现、存储机制、状态机和日志复制四个方面。基本上完成了Raft实现的核心实现。但SOFAJRaft还有更多核心及优化,因为篇幅原因没有进入细细剖析。如果咱们自实现Raft协议,基本上也是实现这几个主流程即可完成简版Raft了。关于Raft协议暂时先告一段路,接下去准备开写ZAB协议。
![]()
- 作者介绍 -
林淮川
毕业于西安交通大学;奈学教育《百万架构师训练营》讲师、企业级源码内源负责人,前大树金融高级架构师、技术委员会开创者、技术总监;前天阳宏业交易事业部技术主管;多年互联网金融行业(ToB)经验。
![]()
本文分享自微信公众号 - 川聊架构(gh_44ec4115d261)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。