1 SOFAJRaft是什么?
Scalable Open Financial Architecture Stack 是蚂蚁金服自主研发的金融级分布式架构,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。
SOFAJRaft 是一个基于 Raft 一致性算法的生产级高性能 Java 实现,适用于高负载低延迟的场景。SOFAJRaft 是从百度的 braft 移植而来,做了一些优化和改进。
GitHub 地址:https://github.com/sofastack/sofa-jraft
文档地址:https://www.sofastack.tech/projects/sofa-jraft/overview/
SOFAJRaft笔记:https://www.yuque.com/huarou/gd4szw/zon6t9
2 SOFAJRaft用户
此处列出了已知在生产环境使用了 SOFAStack 全部或者部分组件的公司或组织。以下排名不分先后:
3 SOFAJRaft设计图
3.1 一个节点内部设计
①Node:Raft 分组中的一个节点,连接封装底层的所有服务,用户看到的主要服务接口,特别是 apply(task)
用于向 raft group 组成的复制状态机集群提交新任务应用到业务状态机。
②存储:上图靠下的部分均为存储相关。
a.Log 存储,记录 Raft 用户提交任务的日志,将日志从 Leader 复制到其他节点上。
LogStorage 是存储实现,默认实现基于 RocksDB 存储,你也可以很容易扩展自己的日志存储实现;
LogManager 负责对底层存储的调用,对调用做缓存、批量提交、必要的检查和优化。
b.Metadata 存储,元信息存储,记录 Raft 实现的内部状态,比如当前 term、投票给哪个节点等信息。
c.Snapshot 存储,用于存放用户的状态机 snapshot 及元信息,可选:
SnapshotStorage 用于 snapshot 存储实现;
SnapshotExecutor 用于 snapshot 实际存储、远程安装、复制的管理。
③状态机:
- StateMachine:用户核心逻辑的实现,核心是
onApply(Iterator)
方法, 应用通过Node#apply(task)
提交的日志到业务状态机; - FSMCaller:封装对业务 StateMachine 的状态转换的调用以及日志的写入等,一个有限状态机的实现,做必要的检查、请求合并提交和并发处理等。
④复制:
- Replicator:用于 Leader 向 Followers 复制日志,也就是 Raft 中的 AppendEntries 调用,包括心跳存活检查等;
- ReplicatorGroup:用于单个 Raft group 管理所有的 replicator,必要的权限检查和派发。
Node 代表了一个 SOFAJRaft Server 节点,这些方框代表他内部的各个模块,我们用银行账户系统举例来说明 SOFAJRaft 的各模块是如何工作的。
⑤RPC:RPC 模块用于节点之间的网络通讯
- RPC Server:内置于 Node 内的 RPC 服务器,接收其他节点或者客户端发过来的请求,转交给对应服务处理;
- RPC Client:用于向其他节点发起请求,例如投票、复制日志、心跳等。
⑥KV Store:
- KV Store 是各种 Raft 实现的一个典型应用场景,SOFAJRaft 中包含了一个嵌入式的分布式 KV 存储实现(SOFAJRaft-RheaKV)。
使用银行账户系统举例来说明 SOFAJRaft 的各模块是如何工作的。
当 Client 向 SOFAJRaft 发来一个“存 100 元”的命令之后,Node 的 Log 存储模块首先将这个命令以 Log 的形式存储到本地,同时 Replicator (复制器)会把这个 Log 复制给其他的 Node,Replicator 是有多个的,集群中有多少个 Follower 就会有多少个 Replicator,这样就能实现并发的日志复制。当 Node 收到集群中半数以上的 Node 返回的“复制成功” 的响应之后,就可以把这条 Log 以及之前的 Log 有序的送到状态机里去执行了。状态机是由用户来实现的,比如我们现在举的例子是银行账户系统,所以状态机执行的就是账户金额的借贷操作。如果 SOFAJRaft 在别的场景中使用,状态机就会有其他的执行方式。
Meta Storage(元存储) 是用来存储记录 Raft 实现的内部状态,比如当前 Term 、投票给哪个节点等信息。
Snapshot 是快照,所谓快照就是对数据当前值的一个记录,Leader 生成快照有这么几个作用:
- 当有新的 Node 加入集群的时候,不用只靠日志复制、回放去和 Leader 保持数据一致,而是通过安装 Leader 的快照来跳过早期大量日志的回放;
- Leader 用快照替代 Log 复制可以减少网络上的数据量;
- 用快照替代早期的 Log 可以节省存储空间。
3.2 三副本的架构图
刚才是一个节点内部的情况,那在 Raft Group 中至少需要 3 个节点,所以这是一个三副本的架构图。
4 运行SOFAJRaft Counter 例子
4.1 启动客户端
程序终止:
Usage : java com.alipay.sofa.jraft.example.counter.CounterServer {dataPath} {groupId} {serverId} {initConf}
Example: java com.alipay.sofa.jraft.example.counter.CounterServer /tmp/server1 counter 127.0.0.1:8081 127.0.0.1:8081,127.0.0.1:8082,127.0.0.1:8083
配置运行:
/tmp/server1 counter 127.0.0.1:8081 127.0.0.1:8081,127.0.0.1:8082,127.0.0.1:8083
启动节点1之后日志信息中出现报错,发现是连接不上8082、8083节点。
在IDEA的Run/Debug Configuration中启动多实例运行:
配置节点二,节点三:
4.2 启动服务端
启动后终止程序:
Usage : java com.alipay.sofa.jraft.example.counter.CounterClient {groupId} {conf}
Example: java com.alipay.sofa.jraft.example.counter.CounterClient counter 127.0.0.1:8081,127.0.0.1:8082,127.0.0.1:8083
增加配置:
运行结果:
4.3 查看生成日志
生成日志目录:
log目录:
meta目录:
记录 Raft 实现的内部状态,比如当前 term、投票给哪个节点等信息。
snapshot目录:
__raft_snapshot_meta:快照数据。
data:最后一个共识的数据。
评论