raft4j 是一个我的基于 RAFT 一致性算法的高性能 Java 实现,其核心功能围绕分布式系统中的一致性协议展开。
整体架构
raft4j 的架构设计清晰,核心模块围绕 RAFT 协议的三个部分展开:
- Leader 选举
确保在任何时间只有一个有效的 Leader 承担写入请求。 - 日志复制
保证日志在所有节点上的一致性。 - 日志应用和状态机
将日志应用到状态机,提供最终一致的系统状态。
raft4j 通过高度模块化的设计,将这些功能封装为可复用的组件,用户可以直接使用其内置的分布式 KV 存储,或者基于其实现自定义的应用。
源码核心模块
raft4j 的源码分布在多个核心包中,每个包对应一个功能模块。以下是关键模块的介绍:
1. 核心模块
org.fbs.raft4jcore
- 实现了 RAFT 协议的核心逻辑,包括:
- 选举过程:定时器触发 Leader 选举。
- 日志复制:Leader 将日志条目复制到 Follower。
- 状态转换:状态机管理节点的角色(Leader、Follower、Candidate)。
- 核心类:
NodeImpl
:RAFT 节点的核心实现类,负责处理节点角色的状态切换和核心 RAFT 流程。BallotBox
:管理日志条目的提交状态。LogManager
:负责日志的存储、读取和快照管理。FSMCaller
:将日志应用到用户定义的有限状态机(Finite State Machine, FSM)。
- 实现了 RAFT 协议的核心逻辑,包括:
2. 日志管理
org.fbs.raft4jstorage
- 提供日志存储和快照功能。
- 核心类:
LogStorage
:抽象接口,定义日志存储的操作。RocksDBLogStorage
:基于 RocksDB 的日志存储实现。SnapshotStorage
:管理快照的存储和恢复。
- 用户可以自定义存储实现,但默认的 RocksDB 实现已经足够高效。
3. 网络通信
org.fbs.raft4jrpc
- 实现了节点之间的通信,基于 Bolt 框架构建。
- 核心类:
RpcServer
:处理来自其他节点的 RPC 请求。RpcClient
:向其他节点发送 RPC 请求。AppendEntriesRequest
和RequestVoteRequest
:实现日志复制和选举的核心 RPC 消息。
- 用户可以扩展通信层,但默认实现已经支持高性能的点到点通信。
4. 状态机
org.fbs.raft4j.entity
- 提供状态机数据结构和日志条目定义。
- 核心类:
RaftOutter.Entry
:定义日志条目。Configuration
:管理集群成员配置。
- 用户需要实现自定义的状态机接口(
StateMachine
),以将日志应用到业务逻辑。
5. 分布式 KV 存储
org.fbs.raft4jexample.counter
- 内置的分布式 KV 存储示例,演示了如何使用 raft4j 构建应用。
- 核心类:
CounterStateMachine
:状态机实现,维护计数器状态。CounterClient
和CounterServer
:客户端和服务端实现。
6. 选举与一致性
org.fbs.raft4j.closure
- 定义了回调接口,用于异步处理请求的结果。
- 核心类:
Closure
:RAID 操作的回调接口,用户可以在操作完成后执行额外逻辑。ReadIndexClosure
和LogEntryClosure
:处理线性一致性读和日志条目复制的回调。
7. 配置管理
org.fbs.raft4j.conf
- 负责管理集群的配置变更(如节点的增加和删除)。
- 核心类:
Configuration
:记录集群成员列表。ConfigurationEntry
:管理配置变更历史。
8. 性能监控
org.fbs.raft4j.util
- 提供性能监控工具。
- 核心类:
Metrics
:基于 Dropwizard Metrics 实现的性能指标收集。Timer
:精确的计时器工具。
核心类关系图
以下是一些核心类之间的关系:
NodeImpl
├── LogManager
├── BallotBox
├── FSMCaller
├── RpcServer
└── RpcClient
NodeImpl
是 RAFT 节点的核心类,协调日志管理(LogManager
)、状态机调用(FSMCaller
)和网络通信(RpcServer
/RpcClient
)。LogManager
管理日志的存储和复制,通过BallotBox
确认日志是否已提交。FSMCaller
将日志应用到用户定义的状态机。
代码运行流程
1. 节点启动
- 用户通过
NodeImpl
启动一个节点实例。 - 节点初始化时会:
- 加载日志和快照。
- 启动 RPC 服务,监听来自其他节点的消息。
- 启动选举定时器。
2. Leader 选举
- 节点进入 Candidate 状态,向其他节点发送
RequestVote
请求。 - 如果获得多数票,节点成为 Leader;否则,重新进入 Candidate 状态。
3. 日志复制
- Leader 接收到写请求后,将日志追加到自身的日志存储中。
- Leader 向 Follower 发送
AppendEntries
请求,保证日志复制到多数节点。
4. 日志提交
- Leader 收到多数 Follower 的确认后,提交日志。
- 日志被提交后,调用
FSMCaller
将日志应用到状态机。
5. 配置变更
- 用户可以动态添加或删除节点。
- 配置变更通过特殊的日志条目(
ConfigurationEntry
)传播到所有节点。
SOFAJRaft 的模块化设计清晰且功能丰富,每个模块都对应分布式系统中某个特定的功能。这些模块协同工作,共同实现了基于 RAFT 协议的分布式一致性框架。以下是对每个模块的详细解读:
1. 核心模块:org.fbs.raft4j.core
职责
实现 RAFT 协议的核心逻辑,包括节点角色的状态管理(Leader、Follower、Candidate)、日志复制、选举和节点间的状态转换。
主要类
-
NodeImpl
- 是 RAFT 节点的核心实现类,负责协调整个 RAFT 流程。
- 职责:
- 管理节点的生命周期:启动(start)、停止(shutdown)。
- 处理节点的角色状态切换(Follower、Candidate、Leader)。
- 协调日志复制、选举、配置变更等核心功能。
- 核心方法:
handleVoteRequest
:处理选举请求。handleAppendEntriesRequest
:处理日志复制请求。stepDown
:节点降级为 Follower。
-
BallotBox
- 负责管理日志条目的提交状态。
- 职责:
- 确定日志条目是否获得多数派确认。
- 通知日志条目是否可以被提交。
-
LogManager
- 管理日志的存储和读取。
- 职责:
- 将日志追加到存储中。
- 检索未提交的日志条目。
- 触发日志的快照操作。
-
FSMCaller
- 负责将日志应用到有限状态机(FSM)。
- 职责:
- 调用用户实现的状态机(
StateMachine
),将日志条目应用到业务逻辑中。 - 提供异步和同步调用支持。
- 调用用户实现的状态机(
-
Replicator
- 用于维护 Leader 和 Follower 之间的日志复制。
- 职责:
- 负责将日志从 Leader 发送到 Follower。
- 确保日志复制的高效性和可靠性。
模块特点
- 状态管理清晰:通过分层的状态管理逻辑,确保节点可以快速响应网络分区、Leader 选举等复杂场景。
- 日志复制高效:使用流水线机制(Replication Pipeline)优化日志的复制性能。
2. 日志管理模块:org.fbs.raft4j.storage
职责
管理日志的存储、读取和快照功能,确保数据的持久化和一致性。
主要类
-
LogStorage
(接口)- 抽象日志存储的功能,包括日志的写入、读取和删除。
- 默认实现:
RocksDBLogStorage
:基于 RocksDB 的高性能日志存储实现。
-
SnapshotStorage
(接口)- 管理快照的存储和恢复操作。
- 默认实现:
LocalSnapshotStorage
:本地文件系统的快照存储实现。
-
LogManager
- 负责协调日志存储(
LogStorage
)和快照存储(SnapshotStorage
)。 - 职责:
- 追加日志条目。
- 检索日志条目或快照。
- 触发日志压缩以减少存储空间占用。
- 负责协调日志存储(
模块特点
- 高性能存储:借助 RocksDB 提供高效的写入和随机读取能力。
- 快照支持:通过快照机制减少日志存储开销,支持快速恢复。
3. 网络通信模块:org.fbs.raft4j.rpc
职责
实现 RAFT 节点之间的通信,包括日志复制、选举等关键功能。
主要类
-
RpcServer
- 负责接收和处理来自其他节点的 RPC 请求。
- 核心功能:
- 接收
RequestVoteRequest
(选举请求)。 - 接收
AppendEntriesRequest
(日志复制请求)。
- 接收
-
RpcClient
- 向其他节点发送 RPC 请求。
- 核心功能:
- 发送选举请求。
- 发送日志复制请求。
-
AppendEntriesRequest
和RequestVoteRequest
- 定义了日志复制和选举的核心数据结构。
- 通过序列化方式(如 Protobuf)进行网络传输。
模块特点
- 高性能通信:基于 Bolt 框架实现了高效的 RPC 通信。
- 可扩展性强:用户可以自定义通信层实现,替换默认的 Bolt 框架。
4. 状态机模块:org.fbs.raft4jentity
职责
定义状态机相关的数据结构和接口,帮助用户实现业务逻辑。
主要类
-
StateMachine
(接口)- 用户需要实现该接口,将日志条目应用到业务逻辑中。
- 核心方法:
onApply
:将日志条目应用到状态机。onSnapshotSave
:保存快照。onSnapshotLoad
:加载快照。
-
RaftOutter.Entry
- 定义日志条目的数据结构。
- 包括日志的索引、Term 和实际数据。
-
Configuration
- 管理集群的成员信息,包括所有节点的地址。
模块特点
- 用户可扩展性:用户可以通过实现
StateMachine
接口,将框架与业务逻辑无缝集成。 - 灵活的日志管理:支持线性一致性读(
ReadIndex
)、状态机快照等高级功能。
5. 分布式 KV 存储示例:org.fbs.raft4.jexample.counter
职责
提供一个内置的分布式 KV 存储示例,演示如何使用 SOFAJRaft 构建分布式应用。
主要类
-
CounterStateMachine
- 实现了一个简单的计数器状态机。
- 核心逻辑:
- 接收加/减的操作日志。
- 更新计数器的值。
-
CounterClient
- 客户端实现,用于向集群发送写入和读取请求。
-
CounterServer
- 服务端实现,启动 RAFT 节点并处理客户端请求。
6. 配置管理模块:org.fbs.raft4j.conf
职责
实现集群成员的动态管理,包括添加、删除和替换节点。
主要类
-
Configuration
- 记录集群的成员信息。
- 支持动态更新。
-
ConfigurationEntry
- 管理配置变更的历史记录。
模块特点
- 动态配置变更:支持在线增删节点而无需停机。
- 一致性保证:通过特殊的日志条目将配置变更同步到所有节点。
7. 性能监控模块:org.fbs.raft4j.util
职责
提供性能指标的采集和监控工具。
主要类
-
Metrics
- 基于 Dropwizard Metrics 实现,收集和暴露性能指标。
- 监控项包括:
- RPC 调用耗时。
- 日志复制延迟。
- Leader 选举耗时。
-
Timer
- 精确计时工具,用于性能分析。