浅谈分布式一致性:Raft 与 SOFAJRaft

沙海 2021年6月2日12:21:56Java评论30字数 10128阅读33分45秒阅读模式
摘要

浅谈分布式一致性:Raft 与 SOFAJRaft 原创 家纯 阿里技术

浅谈分布式一致性:Raft 与 SOFAJRaft

原创 家纯 阿里技术 文章源自JAVA秀-https://www.javaxiu.com/28173.html

收录于话题文章源自JAVA秀-https://www.javaxiu.com/28173.html

#Java50文章源自JAVA秀-https://www.javaxiu.com/28173.html

#分布式系统与计算19文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

一  分布式共识算法 (Consensus Algorithm)文章源自JAVA秀-https://www.javaxiu.com/28173.html

1  如何理解分布式共识?文章源自JAVA秀-https://www.javaxiu.com/28173.html

多个参与者针对某一件事达成完全一致:一件事,一个结论。文章源自JAVA秀-https://www.javaxiu.com/28173.html

已达成一致的结论,不可推翻。文章源自JAVA秀-https://www.javaxiu.com/28173.html

2  有哪些分布式共识算法?文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Paxos:被认为是分布式共识算法的根本,其他都是其变种,但是 paxos 论文中只给出了单个提案的过程并没有给出复制状态机中需要的 multi-paxos 的相关细节的描述,实现 paxos 具有很高的工程复杂度(如多点可写,允许日志空洞等)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Zab:被应用在 zookeeper 中,业界使用广泛,但没用抽象成通用 library。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Raft:以容易理解著称,业界也涌现出很多 raft 实现比如 etcd、braft、tikv 等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

二  Raft 介绍文章源自JAVA秀-https://www.javaxiu.com/28173.html

1  特点:Strong Leader文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 系统中必须存在且同一时刻只能有一个 leader只有 leader 可以接受 clients 发过来的请求。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 负责主动与所有 followers 通信负责将“提案”发送给所有followers同时收集多数派的 followers 应答。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 还需向所有 followers 主动发送心跳维持领导地位(保持存在感)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

另外身为 leader 必须保持一直 heartbeat 的状态。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

2  复制状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

对于一个无限增长的序列a[1, 2, 3…]如果对于任意整数i, a[i]的值满足分布式一致性, 这个系统就满足一致性状态机的要求。文章源自JAVA秀-https://www.javaxiu.com/28173.html

基本上所有的真实系统都会有源源不断的操作这时候单独对某个特定的值达成一致显然是不够的。为了让真实系统保证所有的副本的一致性,通常会把操作转化为 write-ahead-log(WAL)。然后让系统中所有副本对 WAL 保持一致,这样每个副本按照顺序执行 WAL 里的操作,就能保证最终的状态是一致的。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Client 向 leader 发送写请求。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 把“操作”转化为 WAL 写本地 log 的同时也将 log 复制到所有 followers。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 收到多数派应答将 log 对应的“操作”应用到状态机。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 回复 client 处理结果。文章源自JAVA秀-https://www.javaxiu.com/28173.html

3  Raft 中的基本概念文章源自JAVA秀-https://www.javaxiu.com/28173.html

Raft-node 的 3 种角色/状态文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Follower:完全被动不能发送任何请求, 只接受并响应来自 leader 和 candidate 的 message, node启动后的初始状态必须是 follower。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader:处理所有来自客户端的请求以及复制 log 到所有 followers。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Candidate:用来竞选一个新 leader (candidate 由 follower 触发超时而来)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Message 的 3 种类型文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • RequestVote RPC:Candidate 发出。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • AppendEntries (Heartbeat) RPCLeader 发出。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • InstallSnapshot RPCLeader 发出。文章源自JAVA秀-https://www.javaxiu.com/28173.html

任期逻辑时钟文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 时间被划分为一个个任期(term)term id 按时间轴单调递增。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 每一个任期的开始都是 leader 选举选举成功之后leader在任期内管理整个集群, 也就是“选举 + 常规操作”。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 每个任期最多一个 leader可以没有 leader (spilt-vote 导致)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

4  Raft 功能分解文章源自JAVA秀-https://www.javaxiu.com/28173.html

Leader 选举文章源自JAVA秀-https://www.javaxiu.com/28173.html

超时驱动:Heartbeat / Election timeout文章源自JAVA秀-https://www.javaxiu.com/28173.html

随机的超时时间:降低选举碰撞导致选票被瓜分的概率文章源自JAVA秀-https://www.javaxiu.com/28173.html

选举流程:Follower --> Candidate (选举超时触发)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 赢得选举:Candidate --> Leader文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 另一个节点赢得选举:Candidate --> Follower文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 一段时间内没有任何节点器赢得选举:Candidate --> Candidate文章源自JAVA秀-https://www.javaxiu.com/28173.html

文章源自JAVA秀-https://www.javaxiu.com/28173.html

选举动作:文章源自JAVA秀-https://www.javaxiu.com/28173.html

文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Current term++文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 发送 RequestVote RPC文章源自JAVA秀-https://www.javaxiu.com/28173.html

New Leader 选取原则 (最大提交原则):文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Candidates include log info in RequestVote RPCs(index & term of last log entry)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • During elections, choose candidate with log most likely to contain all committed entries文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Voting server V denies vote if its log is “more complete”:(lastTermV > lastTermC) ||((lastTermV == lastTermC) && (lastIndexV > lastIndexC))文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader will have “most complete” log among electing majority文章源自JAVA秀-https://www.javaxiu.com/28173.html

安全性:一个 term最多选出一个 leader可以没 leader下一个 term 再选。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

影响 raft 选举成功率的几个时间参数:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • RTT(Round Trip Time):网络延时文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Heartbeat timeout:心跳间隔,通常应该比 election timeout 小一个数量级,目的是让 leader 能够持续发送心跳来阻止 followers 触发选举文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Election timeout:Leader 与 followers 间通信超时触发选举的时间文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • MTBF(Meantime Between Failure):Servers 连续常规故障时间间隔 RTT << Heartbeat timeout < Election timeout(ET) << MTBF文章源自JAVA秀-https://www.javaxiu.com/28173.html

随机选主触发时间Random(ET, 2ET)文章源自JAVA秀-https://www.javaxiu.com/28173.html

日志复制文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

Raft 日志格式:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • (TermId, LogIndex, LogValue)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 其中 (TermId, LogIndex) 能确定唯一一条日志文章源自JAVA秀-https://www.javaxiu.com/28173.html

Log replication关键点:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 连续性:日志不允许出现空洞文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 有效性:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 不同节点拥有相同 term 和 logIndex 的日志 value 一定相同文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 上的日志一定是有效的文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Follower 上的日志是否有效通过 leader 日志对比判断 (How?)文章源自JAVA秀-https://www.javaxiu.com/28173.html

Followers 日志有效性检查:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • AppendEntries RPC 中还会携带前一条日志的唯一标识 (prevTermId, prevLogIndex)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 递归推导文章源自JAVA秀-https://www.javaxiu.com/28173.html

Followers 日志恢复:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 将 nextIndex 递减并重发 AppendEntries直到与 leader 日志一致文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

Commit Index 推进文章源自JAVA秀-https://www.javaxiu.com/28173.html

CommitIndex (TermId, LogIndex) :文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 所谓 commitIndex就是已达成多数派可以应用到状态机的最新的日志位置文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 日志被复制到 followers 后先持久化并不能马上被应用到状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 只有 leader 知道日志是否达成多数派是否可以应用到状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Followers 记录 leader 发来的当前 commitIndex所有小于等于 commitIndex 的日志均可以应用到状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

CommitIndex推进:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 在下一个 AppendEntries RPC (也包括 Heartbeat)中携带当前的 commitIndex文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Followers 检查日志有效性通过则接受 AppendEntries 并同时更新本地 commitIndex, 最后把所有小于等于 commitIndex 的日志应用到状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

AppendEntries RPC文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 完整信息(currentTerm, logEntries[], prevTerm, prevLogIndex, commitTerm, commitLogIndex)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • currentTerm, logEntries[]日志信息为了效率日志通常为多条文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • prevTerm, prevLogIndex日志有效性检查文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • commitTerm, commitLogIndex:最新的提交日志位点(commitIndex)文章源自JAVA秀-https://www.javaxiu.com/28173.html

阶段小结:现在我们能用 raft 做什么?文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 连续确定多个提案,确保集群中各个系统节点状态完全一致文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 自动选主,保证在只有少数派宕机的情况下持续可用文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 日志强同步,宕机后零数据丢失文章源自JAVA秀-https://www.javaxiu.com/28173.html

三  SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

一个纯 Java 的 raft 算法实现库使用 Java 重写了所有功能,并有一些改进和优化。文章源自JAVA秀-https://www.javaxiu.com/28173.html

1  SOFAJRaft 整体功能文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

功能支持文章源自JAVA秀-https://www.javaxiu.com/28173.html

Leader election:选主。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Log replication and recovery:日志复制和日志恢复log recovery就是要保证已经被 commit 的数据一定不会丢失log recovery 包含两个方面文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Current term 日志恢复,主要针对一些 follower 节点重启加入集群或者是新增 follower 节点文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Prev term 日志恢复,主要针对 leader 切换前后的日志一致性文章源自JAVA秀-https://www.javaxiu.com/28173.html

Snapshot and log compaction:定时生成 snapshot实现 log compaction加速启动和恢复以及InstallSnapshot 给 followers 拷贝数据。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

Membership change:集群线上配置变更增加节点、删除节点、替换节点等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Transfer leader:主动变更 leader用于重启维护leader 负载平衡等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Symmetric network partition tolerance:对称网络分区容忍性。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

Pre-Vote:如上图 S1 为当前 leader网络分区造成 S2 不断增加本地 term为了避免网络恢复后S2发起选举导致正在良心工作的 leader step-down, 从而导致整个集群重新发起选举在 request-vote 之前会先进行 pre-vote(currentTerm + 1lastLogIndex, lastLogTerm)多数派成功后才会转换状态为 candidate 发起真正的 request-vote所以分区后的节点,pre-vote不会成功也就不会导致集群一段时间内无法正常提供服务。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Asymmetric network partition tolerance:非对称网络分区容忍性。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

如上图 S1 为当前 leaderS2 不断超时触发选主S3 提升 term 打断当前 lease从而拒绝 leader 的更新这个时候可以增加一个 trick 的检查每个 follower 维护一个时间戳记录收到 leader 上数据更新的时间(也包括心跳)只有超过 election timeout 之后才允许接受 request-vote 请求。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Fault tolerance:容错性少数派故障不影响系统整体可用性。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 机器掉电文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 强杀应用文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 慢节点(GC, OOM等)文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 网络故障文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 其他各种奇葩原因导致 raft 节点无法正常工作文章源自JAVA秀-https://www.javaxiu.com/28173.html

Workaround when quorate peers are dead:多数派故障时整个 grop 已不具备可用性, 安全的做法是等待多数节点恢复只有这样才能保证数据安全但是如果业务更追求可用性放弃数据一致性的话可以通过手动 reset_peers 指令迅速重建整个集群恢复集群可用。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Metrics:SOFAJRaft 内置了基于 metrics 类库的性能指标统计具有丰富的性能统计指标。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Jepsen:除了单元测试之外SOFAJRaft 还使用 jepsen 这个分布式验证和故障注入测试框架模拟了很多种情况都已验证通过。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机分区,一大一小两个网络分区文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机增加和移除节点文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机停止和启动节点文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机 kill -9 和启动节点文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机划分为两组互通一个中间节点模拟分区情况文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 随机划分为不同的 majority 分组文章源自JAVA秀-https://www.javaxiu.com/28173.html

性能优化文章源自JAVA秀-https://www.javaxiu.com/28173.html

Batch:SOFAJRaft 中整个链路都是 batch 的依靠 disruptor 中的 MPSC 模型批量消费包括但不限于文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 批量提交 task文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 批量网络发送文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 本地 IO batch 写入,要保证日志不丢,一般每一条 log entry 都要进行 fsync, 比较耗时,SOFAJRaft 中做了合并写入的优化文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 批量应用到状态机文章源自JAVA秀-https://www.javaxiu.com/28173.html

Replication pipeline:流水线复制leader 跟 followers 节点的 log 同步是串行 batch 的方式每个 batch 发送之后需要等待 batch 同步完成之后才能继续发送下一批(ping-pong), 这样会导致较长的延迟。可以通过 leader 跟 followers 节点之间的 pipeline 复制来改进有效降低更新的延迟, 提高吞吐。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Append log in parallel:Leader 持久化 log entries 和向 followers 发送 log entries 是并行的。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Fully concurrent replication:Leader 向所有 follwers 发送 log 也是完全并发的。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Asynchronous:Jraft 中整个链路几乎没有任何阻塞完全异步的是一个 callback 编程模型。文章源自JAVA秀-https://www.javaxiu.com/28173.html

ReadIndex:优化 raft read 走 raft log 的性能问题每次 read仅记录 commitIndex然后发送所有 peers heartbeat 来确认 leader 身份如果 leader 身份确认成功等到 applied index >= commitIndex就可以返回 client read 了基于 ReadIndex 可以很方便的提供线性一致读不过 commitIndex 是需要从 leader 那里获取的多了一轮RPC。文章源自JAVA秀-https://www.javaxiu.com/28173.html

Lease Read:通过租约(lease)保证 leader 的身份从而省去了 readIndex 每次 heartbeat 确认 leader 身份性能更好, 但是通过时钟维护 lease 本身并不是绝对的安全(jraft 中默认配置是 readIndex因为 readIndex 性能已足够好)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

2  SOFAJRaft 设计文章源自JAVA秀-https://www.javaxiu.com/28173.html

SOFAJRaft - Raft Node文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

Node:Raft 分组中的一个节点,连接封装底层的所有服务,用户看到的主要服务接口,特别是 apply(task) 用于向 raft group 组成的复制状态机集群提交新任务应用到业务状态机。文章源自JAVA秀-https://www.javaxiu.com/28173.html

存储:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Log 存储记录 raft 用户提交任务的日志将从 leader 复制到其他节点上。LogStorage 是存储实现, LogManager 负责对底层存储的调用对调用做缓存、批量提交、必要的检查和优化。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Metadata 存储元信息存储记录 raft 实现的内部状态比如当前 term、投票给哪个节点等信息。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Snapshot 存储用于存放用户的状态机 snapshot 及元信息,可选. SnapshotStorage 用于 snapshot 存储实现SnapshotExecutor 用于 snapshot 实际存储、远程安装、复制的管理。文章源自JAVA秀-https://www.javaxiu.com/28173.html

状态机:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • StateMachine:用户核心逻辑的实现核心是 onApply(Iterator) 方法应用通过 Node#apply(task) 提交的日志到业务状态机。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • FSMCaller:封装对业务 StateMachine 的状态转换的调用以及日志的写入等一个有限状态机的实现, 做必要的检查、请求合并提交和并发处理等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

复制:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Replicator:用于 leader 向 followers 复制日志也就是 raft 中的 AppendEntries 调用包括心跳存活检查等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • ReplicatorGroup:用于单个 raft group 管理所有的 replicator必要的权限检查和派发。文章源自JAVA秀-https://www.javaxiu.com/28173.html

RPC 模块用于节点之间的网络通讯:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • RPC Server:内置于 Node 内的 RPC 服务器接收其他节点或者客户端发过来的请求, 转交给对应服务处理。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • RPC Client用于向其他节点发起请求例如投票、复制日志、心跳等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

KV Store:SOFAJRaft 只是一个 lib,KV Store 是 SOFAJRaft 的一个典型的应用场景,把它放进图中以便更好的理解 SOFAJRaft。文章源自JAVA秀-https://www.javaxiu.com/28173.html

SOFAJRaft - Raft Group文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

SOFAJRaft - Multi Raft Group文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

3  SOFAJRaft 实现细节文章源自JAVA秀-https://www.javaxiu.com/28173.html

高效的线性一致读文章源自JAVA秀-https://www.javaxiu.com/28173.html

什么是线性一致读?文章源自JAVA秀-https://www.javaxiu.com/28173.html

所谓线性一致读一个简单的例子就是在 t1 的时刻我们写入了一个值, 那么在 t1 之后 我们一定能读到这个值不可能读到 t1 之前的旧值 (想想 Java 中的 volatile 关键字说白了线性一致读就是在分布式系统中实现 volatile 语义)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

上图Client A、B、C、D均符合线性一致读其中 D 看起来是 stale read其实并不是 D 请求横跨了3个阶段而读可能发生在任意时刻所以读到 1 或 2 都行。文章源自JAVA秀-https://www.javaxiu.com/28173.html

重要:接下来的讨论均基于一个大前提就是业务状态机的实现必须是满足线性一致性的, 简单说就是也要具有 Java volatile 的语义。文章源自JAVA秀-https://www.javaxiu.com/28173.html

1)直接点是否可以直接从当前 leader 节点读?文章源自JAVA秀-https://www.javaxiu.com/28173.html

怎么确定当前的 leader 真的是 leader(网络分区)文章源自JAVA秀-https://www.javaxiu.com/28173.html

2)最简单的实现方式:读请求走一遍 raft 协议文章源自JAVA秀-https://www.javaxiu.com/28173.html

浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

有什么问题?文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 不仅有日志写盘开销还有日志复制的 RPC 开销在读比重较大的系统中是无法接受的文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 还多了一堆的 raft “读日志文章源自JAVA秀-https://www.javaxiu.com/28173.html

3)ReadIndex Read文章源自JAVA秀-https://www.javaxiu.com/28173.html

这是 raft 论文中提到过的一种优化方案具体来说:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 将当前自己 log 的 commit index 记录到一个 local 变量 ReadIndex 里面。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 向其他节点发起一次 heartbeat如果大多数节点返回了对应的 heartbeat response,那么 leader 就能够确定现在自己仍然是 leader (证明了自己是自己)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 等待自己的状态机执行直到 apply index 超过了 ReadIndex这样就能够安全的提供 Linearizable Read 了, 也不必管读的时刻是否 leader 已飘走 (思考:为什么需要等到 apply index 超过了 ReadIndex 才可以执行读请求?)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 执行 read 请求将结果返回给 Client。文章源自JAVA秀-https://www.javaxiu.com/28173.html

通过ReadIndex也可以很容易在 followers 节点上提供线性一致读:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Follower 节点向 leader 请求最新的 ReadIndex。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader执行上面 i ~ iii 的过程(确定自己真的是 leader)并返回 ReadIndex 给 follower。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Follower 等待自己的 apply index 超过了 ReadIndex (有什么问题?慢节点?)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Follower 执行 read 请求,将结果返回给 client。文章源自JAVA秀-https://www.javaxiu.com/28173.html

ReadIndex小结:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 相比较于走 raft log 的方式ReadIndex 读省去了磁盘的开销能大幅度提升吞吐结合 SOFAJRaft 的 batch + pipeline ack + 全异步机制三副本的情况下 leader 读的吞吐接近于 RPC 的上限。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 延迟取决于多数派中最慢的一个 heartbeat response理论上对于降低延时的效果不会非常显著。文章源自JAVA秀-https://www.javaxiu.com/28173.html

4)Lease Read文章源自JAVA秀-https://www.javaxiu.com/28173.html

Lease read 与 ReadIndex 类似但更进一步,不仅省去了 log,还省去了网络交互。它可以大幅提升读的吞吐也能显著降低延时。文章源自JAVA秀-https://www.javaxiu.com/28173.html

基本的思路是 leader 取一个比 election timeout 小的租期(最好小一个数量级),在租约期内不会发生选举,这就确保了 leader 不会变,所以可以跳过 ReadIndex 的第二步, 也就降低了延时。可以看到, Lease read 的正确性和时间是挂钩的,因此时间的实现至关重要,如果漂移严重,这套机制就会有问题。文章源自JAVA秀-https://www.javaxiu.com/28173.html

实现方式:文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 定时 heartbeat 获得多数派响应, 确认 leader 的有效性 (在 SOFAJRaft 中默认的 heartbeat 间隔是 election timeout 的十分之一)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 在租约有效时间内,可以认为当前 leader 是 raft group 内的唯一有效 leader,可忽略 ReadIndex 中的 heartbeat 确认步骤(2)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • Leader 等待自己的状态机执行,直到 apply index 超过了 ReadIndex,这样就能够安全的提供 Linearizable Read 了。文章源自JAVA秀-https://www.javaxiu.com/28173.html

5)更进一步:Wait Free文章源自JAVA秀-https://www.javaxiu.com/28173.html

到此为止 lease 省去了 ReadIndex 的第 2 步(heartbeat),实际上还能再进一步,省去第 3 步。文章源自JAVA秀-https://www.javaxiu.com/28173.html

我们想想前面的实现方案的本质是什么? 当前节点的状态机达到“”这一刻的时间点 相同或者更新的状态。文章源自JAVA秀-https://www.javaxiu.com/28173.html

那么更严格一点的约束就是:当前时刻,当前节点的状态机就是最新的。文章源自JAVA秀-https://www.javaxiu.com/28173.html

问题来了,leader 节点的状态机能保证一定是最新的吗?文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 首先 leader 节点的 log 一定是最新的,即使新选举产生的 leader,它也一定包含全部的 commit log,但它的状态机却可能落后于旧的 leader。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 但是在 leader 应用了自己当前 term 的第一条 log 之后,它的状态机就一定是最新的。文章源自JAVA秀-https://www.javaxiu.com/28173.html

  • 所以可以得出结论:当 leader 已经成功应用了自己 term 的第一条 log 之后,不需要再取 commit index,也不用等状态机,直接读,一定是线性一致读。文章源自JAVA秀-https://www.javaxiu.com/28173.html

小结:Wait Free 机制将最大程度的降低读延迟,SOFAJRaft 暂未实现 wait free 这一优化,不过已经在计划中。文章源自JAVA秀-https://www.javaxiu.com/28173.html

在 SOFAJRaft 中发起一次线性一致读请求:文章源自JAVA秀-https://www.javaxiu.com/28173.html

    // KV 存储实现线性一致读publicvoidreadFromQuorum(String key, AsyncContext asyncContext){// 请求 ID 作为请求上下文传入byte[] reqContext = newbyte[4]; Bits.putInt(reqContext, 0, requestId.incrementAndGet());// 调用 readIndex 方法, 等待回调执行this.node.readIndex(reqContext, new ReadIndexClosure() {@Overridepublicvoidrun(Status status, long index, byte[] reqCtx){if (status.isOk()) {try {// ReadIndexClosure 回调成功, 可以从状态机读取最新数据返回// 如果你的状态实现有版本概念, 可以根据传入的日志 index 编号做读取 asyncContext.sendResponse(new ValueCommand(fsm.getValue(key))); } catch (KeyNotFoundException e) { asyncContext.sendResponse(GetCommandProcessor.createKeyNotFoundResponse()); } } else {// 特定情况下, 比如发生选举, 该读请求将失败 asyncContext.sendResponse(new BooleanCommand(false, status.getErrorMsg())); } } });}
    文章源自JAVA秀-https://www.javaxiu.com/28173.html

    文章源自JAVA秀-https://www.javaxiu.com/28173.html

    四  SOFAJRaft 应用场景文章源自JAVA秀-https://www.javaxiu.com/28173.html

    1  SOFAJRaft 可以做什么文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 选举文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 分布式锁服务,比如 zookeeper文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 高可靠的元信息管理文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 分布式存储系统,如分布式消息队列、分布式文件系统、分布式块系统等等。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    2  用户案例文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • AntQ Streams QCoordinator:使用 SOFAJRaft 在 coordinator 集群内做选举、元信息存储等功能。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • Schema Registry:高可靠 schema 管理服务,类似 kafka schema registry。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • SOFA 服务注册中心元信息管理模块:IP 数据信息注册,要求写数据达到各个节点一致, 并且在少数派节点挂掉时保证不影响数据正常存储。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • RheaKV:基于 SOFAJRaft 和 rocksDB 实现的嵌入式、分布式、高可用、强一致的 KV 存储类库。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    3  简单实践:基于 SOFAJRaft 设计一个简单的 KV Store文章源自JAVA秀-https://www.javaxiu.com/28173.html

    浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

    到目前为止,我们似乎还没看到 SOFAJRaft 作为一个 lib 有什么特别之处, 因为 SOFAJRaft 能办到的 zk,etcd 似乎基本上也都可以办到, 那么 SOFAJRaft 算不算重复造轮子?文章源自JAVA秀-https://www.javaxiu.com/28173.html

    为了说明 SOFAJRaft 具有很好的想象空间以及扩展能力,下面再介绍一个基于 SOFAJRaft 的复杂一些的实践。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    4  复杂一点的实践:基于 SOFAJRaft 的 Rhea KV 的设计文章源自JAVA秀-https://www.javaxiu.com/28173.html

    浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

    功能名词文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • PD:全局的中心总控节点, 负责整个集群的调度, 不需要自管理的集群可不启用 PD (一个PD可管理多个集群,基于 clusterId 隔离)。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • Store:集群中的一个物理存储节点,一个 store 包含一个或多个 region。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • Region:最小的 KV 数据单元,每个 region 都有一个左闭右开的区间 [startKey, endKey),可根据请求流量/负载/数据量大小等指标自动分裂以及自动副本搬迁。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    特点文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 嵌入式文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 强一致性文章源自JAVA秀-https://www.javaxiu.com/28173.html

    • 自驱动:自诊断,自优化,自决策,自恢复。以上几点(尤其2, 3)基本都是依托于 SOFAJRaft 自身的功能来实现。文章源自JAVA秀-https://www.javaxiu.com/28173.html

    招聘文章源自JAVA秀-https://www.javaxiu.com/28173.html

    我们是蚂蚁智能监控技术中台的存储团队,我们正在使用 Rust/Go/Java 构建高性能、低成本具备实时分析能力的新一代时序数据库,欢迎转岗或者推荐,联系人家纯:jiachun.fjc@antgroup.com文章源自JAVA秀-https://www.javaxiu.com/28173.html

    文章源自JAVA秀-https://www.javaxiu.com/28173.html

    免费领取电子书文章源自JAVA秀-https://www.javaxiu.com/28173.html

    《阿里云技术面试红宝书》文章源自JAVA秀-https://www.javaxiu.com/28173.html

    本书公开30道阿里云技术面试真题,含云原生、大数据、IoT、数据库等领域,精准回顾相关知识点及考察要点,间接地与技术大牛们学习,温故知新!文章源自JAVA秀-https://www.javaxiu.com/28173.html

    扫码加阿里妹好友回复“红宝书”获取吧~(若扫码无效,可通过微信号alimei4、alimei5、alimei6、alimei7直接添加)文章源自JAVA秀-https://www.javaxiu.com/28173.html

    浅谈分布式一致性:Raft 与 SOFAJRaft文章源自JAVA秀-https://www.javaxiu.com/28173.html

    阅读原文文章源自JAVA秀-https://www.javaxiu.com/28173.html

    继续阅读
    速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
    weinxin
    资源分享QQ群
    本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
    沙海
    匿名

    发表评论

    匿名网友 填写信息

    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

    确定