1 背景

在分布式系统应用中,高可用、一致性是经常面临的问题,针对不同的应用场景,我们会选择不同的架构方式,比如master-slave、基于ZooKeeper选主。随着时间的推移,出现了基于Raft算法自动选主的方式,Raft是在Paxos的基础上,做了一些简化和限制,比如增加了日志必须是连续的,只支持领导者、跟随者和候选人三种状态,在理解和算法实现上都相对容易许多。

1)DLedger 是openMessaging发布的一个基于 Raft 实现的JAVA类库,可以方便引用到系统中,满足其高可用、高可靠、强一致的需求,其中在RocketMQ中作为消息Broker存储高可用实现的一种解决方案。

2)Raft将系统中的角色分为领导者(Leader)、跟从者(Follower)和候选人(Candidate):

  • Leader:接受客户端请求,定时发送心跳包,并向Follower同步请求日志,当日志同步到大多数节点上后告诉Follower提交日志。
  • Follower:接受并持久化Leader同步的日志,在Leader告之日志可以提交之后,提交日志。
  • Candidate:Leader选举过程中的临时角色,该状态下的节点会发起投票,尝试选择自己为主节点,选举成功后,不会存在该状态下的节点

2 DLedger架构设计

DLedger 的实现大体可以分为以下两个部分:

  • 选举 Leader
  • 日志复制
  • 其整体架构如下图

注:图引用官网

从上面的架构图中,有两个核心类:DLedgerLeaderElector 和 DLedgerStore,选举和文件存储。选出 leader 后,再由 leader 去接收数据的写入,同时同步到其他的 follower,这样就完成了整个 Raft 的写入过程

3 DLedger选主源码分析

3.1 下载源码

从gitGub下载代码(https://github.com/openmessaging/dledger ),idea引入后,我们发现整个代码量很小,在分析代码时比较容易.

3.2 选主流程分析

3.2.1 原理

raft的选主过程实际是一个状态机的流转,在集群启动时每个节点的等待超时时间时随机的,在第一个节点超时时间到来,则主动向其他节点发起投票,在收到半数以上的投票后晋升为leader(投票过程是个循环的过程),同时发送心跳请求,其他候选节点收到主节点的请求后,改变自己为follower节点。

  • term: 任期,每一轮投票都是一个任期,默认从0开始
  • Quorum机制:简单说就是少说半数以上,比如3个节点,2个同意即可
  • 超时时间: 在选举时,每个节点的超时时间在一定范围内是随机的,这样可以保证能够顺利选举

3.2.2 代码分析

整个状态机的驱动,由线程每个10ms反复执行DLedgerLeaderElector.maintainState()方法。下面重点来分析其状态的驱动:

进入到核心方法maintainAsCandidate() :

1.step1 初始化

  • term : 投票轮次。
  • ledgerEndTermLeader: 节点当前的投票轮次。
  • ledgerEndIndex: 当前日志的最大序列,即下一条日志的开始 index
  • nextTimeToRequestVote: 下次发起投票的时间(随机的)
  • needIncreaseTermImmediately:是否立即投票,在后面中会说明

在DLedger中每个节点的初始状态WAIT_TO_REVOTE,所以第一轮只是做了初始化。其中只有 memberState.nextTerm()这个代码会更改投票轮次

2.step2 投票

进入到核心方法handleVote(),这个方法主要是判断其他节点请求来后,根据自己的term和请求者的等判断是否投赞成票

  • ledgerEndIndex因为在日志复制过程中,每个节点的进度有可能是不一样的,所以在新的一轮选举时,这时不能投赞成票的
  • 被选举者 term 小于 选举者的term,返回拒绝
  • 被选举者 term 大于 选举者的term,则选举者进行下面操作:
    • 变成candidate(或者保持candidate)
    • 把needIncreaseImmediately设置为true。
    • 返回 REJECT_TERM_NOT_READY,这个在后面提到。

这里补充说明:

选举者 的下一次状态循环会进入到maintainAsCandidate()函数,然后因为needIncreaseImmediately为true,所以把term更新,同时重置计时器。 但是并没有立刻发出投票(此时选举者 的CurrVoteFor还是null,使得接下来给之前的voting candidate 投赞成票可能)

获取所有node投票结果后开始计算票数:

3.step3 仲裁

在收到所有节点的投票结果计数后,进行仲裁,这里主要说明下图中这个条件

  • acceptNum:同意的数量
  • notReadyTermNum:未准备好的数量(即结果为REJECT_TERM_NOT_READY)

这里没有重置nextTimeToRequestVote的时间,即刻再发起一次投票。结合上面的说明,这样保证了被选者能尽快去拿到这些notRead的节点的赞成票。

最终经过多次投票后,当一个node节点获取到半数以上投票后,更新自己未leader角色,同时向其他node节点发送heartBeat,其他节点在收到心跳信息后,将自己从candidate 变为follower。

3.3 单元测试验证

3.3.1 编写单元测试

3.3.2 日志分析

3.4 应用场景

  1. DLedger 作为 RocketMQ ( version>=4.5.0)的消息存储已经发布
  2. 基于DLedger 实现多节点的缓存同步更新
  3. 基于日志复制的副本容错处理

4 总结

  1. 这里只简单分析了选主过程,在阅读源码过程中会涉及很多java的基础及netty的使用,比如AQS、CompletableFuture等,有助于提高我们的编码能力。
  2. DLedger在初始化时是将节点角色设置为candidate而不是follower 这个和原Raft是不同的地方,在节点角色转换过程中也稍有差别。

参考文献

作者:京东物流 郭庆海

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

基于Raft算法的DLedger-Library分析的更多相关文章

  1. Fabric2.2中的Raft共识模块源码分析

    引言 Hyperledger Fabric是当前比较流行的一种联盟链系统,它隶属于Linux基金会在2015年创建的超级账本项目且是这个项目最重要的一个子项目.目前,与Hyperledger的另外几个 ...

  2. 10分钟弄懂Raft算法

    分布式系统在极大提高可用性.容错性的同时,带来了一致性问题(CAP理论).Raft算法能够解决分布式系统环境下的一致性问题. 我们熟悉的ETCD注册中心就采用了这个算法:你现在看的这篇微信公众号文章, ...

  3. 分布式系统一致性问题与Raft算法(上)

    最近在做MIT6.824的几个实验,真心觉得每一个做分布式相关开发的程序员都应该去刷一遍(裂墙推荐),肯定能够提高自己的技术认知水平,同时也非常感谢MIT能够把这么好的资源分享出来. 其中第二个实验, ...

  4. 看动画轻松学会 Raft 算法

    由于 Paxos 算法过于晦涩难懂且难以实现,Diego Ongaro 提出了一种更易于理解和实现并能等价于 Paxos 算法的共识算法 - Raft 算法. 因为 Raft 算法清晰易懂越来越多的开 ...

  5. DLedger —基于 raft 协议的 commitlog 存储库

    “点击获取上云帮助文档” 尊敬的阿里云用户: 您好!为方便您试用开源 RocketMQ 客户端访问阿里云MQ,我们申请了专门的优惠券,优惠券可以直接抵扣金额.请填写下您公司账号信息,点击上图,了解更多 ...

  6. R语言︱情感分析—基于监督算法R语言实现(二)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:本文大多内容来自未出版的<数据 ...

  7. 基于Raft深度优化,腾讯云金融级消息队列CMQ高可靠算法详解

    背景介绍 分布式系统是指一组独立的计算机,通过网络协同工作的系统,客户端看来就如同单台机器在工作.随着互联网时代数据规模的爆发式增长,传统的单机系统在性能和可用性上已经无法胜任,分布式系统具有扩展性强 ...

  8. 基于FP-Growth算法的关联性分析——学习笔记

    数据挖掘 比之前的Ap快,因为只遍历两次. 降序 一.构建FP树 对频繁项集排序,以构成共用关系. 二.基于FP树的频繁项分析 看那个模式基出现过几次.频繁度. 看洗发液的 去掉频繁度小的 构建洗发液 ...

  9. 基于K-means聚类算法进行客户人群分析

    摘要:在本案例中,我们使用人工智能技术的聚类算法去分析超市购物中心客户的一些基本数据,把客户分成不同的群体,供营销团队参考并相应地制定营销策略. 本文分享自华为云社区<基于K-means聚类算法 ...

  10. 分布式一致性算法:Raft 算法(论文翻译)

    Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比 Paxos 算法更易懂且更容易实现.本文对 raft 论文进行翻译,希望能有助于读者更方便地理解 raft 的 ...

随机推荐

  1. C语言下载minGW地址

    https://sourceforge.net/projects/mingw-w64/files/ 下载红框内即可

  2. paging组件的用法和意义

    一.Paging组件的意义 分页加载是在应用程序开发过程中十分常见的需求,我们经常需要以列表的方式加载大量的数据,这些数据通常来自网络或本地数据库.然而,如果一次性将所有数据全部加载出来,必然会消耗大 ...

  3. 对比 MyBatis 和 MyBatis-Plus 批量插入、批量更新的性能和区别

    1 环境准备 demo 地址:learn-mybatis · Sean/spring-cloud-alibaba - 码云(gitee.com) 1.1 搭建 MyBatis-Plus 环境 创建 m ...

  4. 最火前端 Web 组态软件 (可视化)

    ​  前言: 随着物联网.大数据等技术高速发展,我们逐步向数字化.可视化的人工智能(AI)时代的方向不断迈进.智能时代是工业 4.0 时代,我国工业领域正努力从"制造"迈向&quo ...

  5. win如何根据端口号查找并杀死一个线程

    查看端口占用 netstat -ano | findstr "端口号" 杀死一个进程 taskkill /pid 进程号 -f

  6. 创建及管理DSW实例

      机器学习PAI 产品概述 快速入门 操作指南 准备工作 工作空间管理 AI计算资源管理 AI开发 开发流程 快速开始 智能标注(iTAG) 可视化建模(PAI-Designer) 交互式建模(PA ...

  7. 高可用mongodb集群(分片+副本):性能测试

    目录 ■ 为指定的库和表指定hash分片 ■ 测试模型,即workload模型 ■ 测试指标 ■ workload_s6 ■ 分片集群性能测试数据统计分析 ■ 测试结论 Yahoo! Cloud Se ...

  8. C++ STL标准容器的特点和典型的使用场景

    概念和作用 C++标准模板库(Standard Template Library,STL)提供了一组通用的模板类和函数,用于处理常见的数据结构和算法.STL中的标准容器是其中的重要组成部分,它们提供了 ...

  9. CSS3之创建3D场景

    1.属性介绍 perspective:800    平面距离三维中方框的距离 perspective-origin:50% 50%   表示从平面上哪个位置看三维图 ,相当于是X轴和Y轴,此时表示平面 ...

  10. IEDA-Maven项目开发步骤

    1. 打开IDEA 界面,选择"New Project" 2. 输入项目名称和基本信息 输入项目名称.选择存放路径.JDK版本.以及GroupId.ArtifactId. Grou ...