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. QA|selenium打开浏览器后没有执行后面的代码(get请求)|UI自动化测试

    Q:selenium打开浏览器后没有执行后面的代码(get请求) 代码如图: 原因:webdriver_path应该给的是chromedriver.exe的路径,而不是chrome.exe的路径,写错 ...

  2. 当开源项目 Issue 遇到了 DevChat

    目录 1. 概述 2. Bug 分析与复现 3. Bug 定位与修复 4. 代码测试 5. 文档更新 6. 提交 Commit 7. 总结 1. 概述 没错,又有人给 GoPool 项目提 issue ...

  3. 怎么搭建web组态

    web组态是指通过可视化拖拽组件的方式,低代码搭建监控大屏.web页面.物联网各行业的数据以及监控场景,每个行业的业务不同,需要展示的页面也不同.组态快速搭建页面的优势,能更好的满足不同定制化监控页面 ...

  4. 逻辑漏洞挖掘之XSS漏洞原理分析及实战演练

    一.前言 2月份的1.2亿条用户地址信息泄露再次给各大公司敲响了警钟,数据安全的重要性愈加凸显,这也更加坚定了我们推行安全测试常态化的决心.随着测试组安全测试常态化的推进,有更多的同事对逻辑漏洞产生了 ...

  5. Solution -「CF 392C」Yet Another Number Sequence

    Description Link. 求 \(\sum_{i=1}^{n}\text{fibonacci}_{i}\times i^{k}=\sum_{i=1}^{n}(F_{i-1}+\text{fi ...

  6. linux中的sar命令

    linux中的sar命令 sar命令的安装 [root@localhost test]# yum install sysstat 安装成功! sar命令说明 语法格式 sar [ 选项 ] [ < ...

  7. spark修改控制台输出日志级别

    spark修改控制台输出日志级别 修改conf/log4j.properties cd $SPARK_HOME/conf cp log4j.properties.template ./log4j.pr ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (106)-- 算法导论10.1 4题

    四.用go语言,重写 ENQUEUE 和 DEQUEUE 的代码,使之能处理队列的下溢和上溢. 文心一言: 在 Go 语言中,我们可以使用切片来实现队列.下面是如何实现 ENQUEUE 和 DEQUE ...

  9. 分布式事务 —— SpringCloud Alibaba Seata

    Seata 简介 传统的单体应用中,业务操作使用同一条连接操作不同的数据表,一旦出现异常就可以整体回滚.随着公司的快速发展.业务需求的变化,单体应用被拆分成微服务应用,原来的单体应用被拆分成多个独立的 ...

  10. 2023_10_09_MYSQL_DAY_01_课后题

    2023_10_09_MYSQL_DAY_01_课后题 #第三章 #1. 查询每名员工的员工姓名,入职时间. SELECT ename, hiredate FROM emp; #2. 查询部门表中部门 ...