Node:Raft 分组中的一个节点,衔接封装底层的一切效劳,用户看到的主要效劳接口,特别是 apply(task)用于向 raft group 组成的复制形状机集群提交新义务运用到业务形状机。
存储:上图靠下的部分均为存储相关。
Log 存储,记载 Raft 用户提交义务的日志,将日志从 Leader 复制到其他节点上。
LogStorage 是存储完成,默许完成基于 RocksDB 存储,你也可以很容易扩展本人的日志存储完成;
LogManager 担任对底层存储的调用,对调用做缓存、批量提交、必要的反省和优化。
Metadata 存储,元信息存储,记载 Raft 完成的外部形状,比如以后 term、投票给哪个节点等信息。
Snapshot 存储,用于寄存用户的形状机 snapshot 及元信息,可选:
SnapshotStorage 用于 snapshot 存储完成;
SnapshotExecutor 用于 snapshot 实践存储、远程安装、复制的管理。
形状机
StateMachine:用户中心逻辑的完成,中心是 onApply(Iterator) 办法, 运用经过 Node#apply(task) 提交的日志到业务形状机;
FSMCaller:封装对业务 StateMachine 的形状转换的调用以及日志的写入等,一个有限形状机的完成,做必要的反省、央求兼并提交和并发处置等。
复制
Replicator:用于 Leader 向 Followers 复制日志,也就是 Raft 中的 AppendEntries 调用,包括心跳存活反省等;
ReplicatorGroup:用于单个 Raft group 管理一切的 replicator,必要的权限反省和派发。
RPC:RPC 模块用于节点之间的网络通讯
RPC Server:内置于 Node 内的 RPC 效劳器,接纳其他节点或许客户端发过去的央求,转交给对应效劳处置;
RPC Client:用于向其他节点发起央求,例如投票、复制日志、心跳等。
KV Store:KV Store 是各种 Raft 完成的一个典型运用场景,SOFAJRaft 中包含了一个嵌入式的散布式 KV 存储完成(SOFAJRaft-RheaKV)。
SOFAJRaft Group
单个节点的 SOFAJRaft-node 是没什么实践意义的,下面是三正本的 SOFAJRaft 架构图:
SOFAJRaft Multi Group单个 Raft group 是无法处置大流量的读写瓶颈的,SOFAJRaft 自然也要支持 multi-raft-group。
SOFAJRaft 完成细节解析之高效的线性分歧读什么是线性分歧读? 所谓线性分歧读,一个复杂的例子就是在 t1 的时辰我们写入了一个值,那么在 t1 之后,我们一定能读到这个值,不能够读到 t1 之前的旧值 (想想 Java 中的 volatile 关键字,说白了线性分歧读就是在散布式系统中完成 Java volatile 语义)。
如上图 Client A、B、C、D 均契合线性分歧读,其中 D 看起来是 stale read,其实并不是,D 央求横跨了 3 个阶段,而读能够发作在恣意时辰,所以读到 1 或 2 都行。
重要:接上去的讨论均基于一个大前提,就是业务形状机的完成必须是满足线性分歧性的,复杂说就是也要具有 Java volatile 的语义。
要完成线性分歧读,首先我们复杂直接一些,能否可以直接从以后 Leader 节点读?
细心一想,这显然行不通,由于你无法确定这一刻以后的 "Leader" 真的是 Leader,比如在网络分区的状况下,它能够曾经被推翻王朝却不自知。
最复杂易懂的完成方式:同 “写” 央求一样,“读” 央求也走一遍 Raft 协议 (Raft Log)。
本图出自《Raft: A Consensus Algorithm for Replicated Logs》
这一定是可以的,但功用上显然不会太出色,走 Raft Log 不只仅有日志落盘的开支,还有日志复制的网络开支,另外还有一堆的 Raft “读日志” 形成的磁盘占用开支,这在读比重很大的系统中通常是无法被接受的。
ReadIndex Read
这是 Raft 论文中提到的一种优化方案,详细来说:
Leader 将本人以后 Log 的 commitIndex 记载到一个 Local 变量 ReadIndex 外面;
接着向 Followers 发起一轮 heartbeat,假设半数以上节点前往了对应的 heartbeat response,那么 Leader 就可以确定如今本人依然是 Leader (证明了本人是本人);
Leader 等候本人的形状机执行,直到 applyIndex 超过了 ReadIndex,这样就可以安全的提供 Linearizable Read 了,也不必管读的时辰能否 Leader 已飘走 (思索:为什么等到 applyIndex 超过了 ReadIndex 就可以执行读央求?);
Leader 执行 read 央求,将结果前往给 Client。
经过ReadIndex,也可以很容易在 Followers 节点上提供线性分歧读:
Follower 节点向 Leader 央求最新的 ReadIndex;
Leader 执行下面前 3 步的进程(确定本人真的是 Leader),并前往 ReadIndex 给 Follower;
Follower 等候本人的 applyIndex 超过了 ReadIndex;
Follower 执行 read 央求,将结果前往给 Client。(SOFAJRaft 中可配置能否从 Follower 读取,默许不翻开)
ReadIndex小结:
相比较于走 Raft Log 的方式,ReadIndex 省去了磁盘的开支,能大幅度提升吞吐,结合 SOFAJRaft 的 batch + pipeline ack + 全异步机制,三正本的状况下 Leader 读的吞吐可以接近于 RPC 的吞吐下限;
延迟取决于少数派中最慢的一个 heartbeat response,实际上关于降低延时的效果不会十分清楚。
Lease Read
Lease Read 与 ReadIndex 相似,但更进一步,不只省去了 Log,还省去了网络交互。它可以大幅提升读的吞吐也能清楚降低延时。
(责任编辑:admin)