上一篇 源码分析 RocketMQ DLedger(多副本) 之日志复制(传播) ,可能有不少读者朋友们觉得源码阅读较为枯燥,看的有点云里雾里,本篇将首先梳理一下 RocketMQ DLedger 多副本关于日志复制的三个核心流程图,然后再思考一下在异常情况下如何保证数据一致性。
@(本节目录)

1、RocketMQ DLedger 多副本日志复制流程图

1.1 RocketMQ DLedger 日志转发(append) 请求流程图

1.2 RocketMQ DLedger 日志仲裁流程图

1.3 RocketMQ DLedger 从节点日志复制流程图

2、RocketMQ DLedger 多副本日志复制实现要点


上图是一个简易的日志复制的模型:图中客户端向 DLedger 集群发起一个写请求,集群中的 Leader 节点来处理写请求,首先数据先存入 Leader 节点,然后需要广播给它的所有从节点,从节点接收到 Leader 节点的数据推送对数据进行存储,然后向主节点汇报存储的结果,Leader 节点会对该日志的存储结果进行仲裁,如果超过集群数量的一半都成功存储了该数据,主节点则向客户端返回写入成功,否则向客户端写入写入失败。

接下来我们来探讨日志复制的核心设计要点。

2.1 日志编号

为了方便对日志进行管理与辨别,raft 协议为一条一条的消息进行编号,每一条消息达到主节点时会生成一个全局唯一的递增号,这样可以根据日志序号来快速的判断数据在主从复制过程中数据是否一致,在 DLedger 的实现中对应 DLedgerMemoryStore 中的 ledgerBeginIndex、ledgerEndIndex,分别表示当前节点最小的日志序号与最大的日志序号,下一条日志的序号为 ledgerEndIndex + 1 。

与日志序号还与一个概念绑定的比较紧密,即当前的投票轮次。

2.2 追加与提交机制

请思考如下问题,Leader 节点收到客户端的数据写入请求后,通过解析请求,提取数据部分,构建日志对象,并生成日志序号,用 seq 表示,然后存储到 Leader 节点中,然后将日志广播(推送)到其从节点,由于这个过程中存在网络时延,如果此时客户端向主节点查询 seq 的日志,由于日志已经存储在 Leader 节点中了,如果直接返回给客户端显然是有问题的,那该如何来避免这种情况的发生呢?

为了解决上述问题,DLedger 的实现(应该也是 raft 协议的一部分)引入了已提交指针(committedIndex)。即当主节点收到客户端请求时,首先先将数据存储,但此时数据是未提交的,此过程可以称之为追加,此时客户端无法访问,只有当集群内超过半数的节点都将日志追加完成后,才会更新 committedIndex 指针,得以是数据能否客户端访问。

一条日志要能被提交的充分必要条件是日志得到了集群内超过半数节点成功追加,才能被认为已提交。

2.3 日志一致性如何保证

从上文得知,一个拥有3个节点的 DLedger 集群,只要主节点和其中一个从节点成功追加日志,则认为已提交,客户端即可通过主节点访问。由于部分数据存在延迟,在 DLedger 的实现中,读写请求都将由 Leader 节点来负责。那落后的从节点如何再次跟上集群的步骤呢?

要重新跟上主节点的日志记录,首先要知道的是如何判断从节点已丢失数据呢?

DLedger 的实现思路是,DLedger 会按照日志序号向从节点源源不断的转发日志,从节点接收后将这些待追加的数据放入一个待写队列中。关键中的关键:从节点并不是从挂起队列中处理一个一个的追加请求,而是首先查阅从节点当前已追加的最大日志序号,用 ledgerEndIndex 表示,然后尝试追加 (ledgerEndIndex + 1)的日志,用该序号从代写队列中查找,如果该队列不为空,并且没有 (ledgerEndIndex + 1)的日志条目,说明从节点未接收到这条日志,发生了数据缺失。然后从节点在响应主节点 append 的请求时会告知数据不一致,然后主节点的日志转发线程其状态会变更为COMPARE,将向该从节点发送COMPARE命令,用来比较主从节点的数据差异,根据比较的差异重新从主节点同步数据或删除从节点上多余的数据,最终达到一致。于此同时,主节点也会对PUSH超时推送的消息发起重推,尽最大可能帮助从节点及时更新到主节点的数据。

更多问题,`欢迎大家留言与我一起探讨。如果觉得文章对自己有些用处的话,麻烦帮忙点个赞,谢谢。


推荐阅读:RocketMQ 日志复制系列文章:
1、源码分析 RocketMQ DLedger 多副本存储实现
2、源码分析 RocketMQ DLedger(多副本) 之日志追加流程
3、源码分析 RocketMQ DLedger(多副本) 之日志复制(传播)


作者介绍:丁威,《RocketMQ技术内幕》作者,RocketMQ 社区布道师,公众号:中间件兴趣圈 维护者,目前已陆续发表源码分析Java集合、Java 并发包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等源码专栏。可以点击链接加入中间件知识星球 ,一起探讨高并发、分布式服务架构,交流源码。

基于 raft 协议的 RocketMQ DLedger 多副本日志复制设计原理的更多相关文章

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

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

  2. 源码分析 RocketMQ DLedger 多副本之 Leader 选主

    目录 1.DLedger关于选主的核心类图 1.1 DLedgerConfig 1.2 MemberState 1.3 raft协议相关 1.4 DLedgerRpcService 1.5 DLedg ...

  3. 源码分析 RocketMQ DLedger(多副本) 之日志复制(传播)

    目录 1.DLedgerEntryPusher 1.1 核心类图 1.2 构造方法 1.3 startup 2.EntryDispatcher 详解 2.1 核心类图 2.2 Push 请求类型 2. ...

  4. 实践案例丨基于 Raft 协议的分布式数据库系统应用

    摘要:简单介绍Raft协议的原理.以及存储节点(Pinetree)如何应用 Raft实现复制的一些工程实践经验. 1.引言 在华为分布式数据库的工程实践过程中,我们实现了一个计算存储分离. 底层存储基 ...

  5. 源码分析 RocketMQ DLedger 多副本存储实现

    目录 1.DLedger 存储相关类图 1.1 DLedgerStore 1.2 DLedgerMemoryStore 1.3 DLedgerMmapFileStore 2.DLedger 存储 对标 ...

  6. RocketMQ 整合 DLedger(多副本)即主从切换实现平滑升级的设计技巧

    目录 1.阅读源码之前的思考 2.从 Broker 启动流程看 DLedger 2.1 构建 DefaultMessageStore 2.2 增加节点状态变更事件监听器 2.3 调用 DefaultM ...

  7. RocketMQ 多副本前置篇:初探raft协议

    目录 1.Leader选举 1.1 一轮投票中,只有一个节点发起投票的情况 1.2 一轮投票中,超过一个节点发起投票的情况 1.3 思考如何实现Raft选主 2.日志复制 Raft协议是分布式领域解决 ...

  8. Docker 部署 RocketMQ Dledger 集群模式( 版本v4.7.0)

    文章转载自:http://www.mydlq.club/article/97/ 系统环境: 系统版本:CentOS 7.8 RocketMQ 版本:4.7.0 Docker 版本:19.03.13 一 ...

  9. Raft协议--中文论文介绍

    本篇博客为著名的 RAFT 一致性算法论文的中文翻译,论文名为<In search of an Understandable Consensus Algorithm (Extended Vers ...

随机推荐

  1. 力扣(LeetCode)整数反转 个人题解

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: ...

  2. LVM弹性硬盘

    LVM机制的基本概念 PV(物理卷) ----由多个pe组成 VG(卷组) LV(逻辑卷) 基本命令: 如: 服务器新增一块大小为1T的SCSI的硬盘(sdb) ,创建一个名字为(ceshi)的逻辑分 ...

  3. Condition对象以及ArrayBlockingQueue阻塞队列的实现(使用Condition在队满时让生产者线程等待, 在队空时让消费者线程等待)

    Condition对象 一).Condition的定义 Condition对象:与锁关联,协调多线程间的复杂协作. 获取与锁绑定的Condition对象: Lock lock = new Reentr ...

  4. [ML机器学习 - Stanford University] - Week1 - 01 Introduction

    What is Machine Learning? Two definitions of Machine Learning are offered. Arthur Samuel described i ...

  5. element 根据某多个属性合并列

    日常渲染 methods: { arraySpanMethod({ row, column, rowIndex, columnIndex }) { // 没办法循环判断具体是那一列 所以就只好写了多个 ...

  6. JavaScript笔记十一

    1.DOM查询 - 通过具体的元素节点来查询 - 元素.getElementsByTagName() - 通过标签名查询当前元素的指定后代元素 - 元素.childNodes - 获取当前元素的所有子 ...

  7. Kubernetes权威指南 第一章:Kubernetes入门

    Kubernetes是什么 官网 https://kubernetes.io/ 中文版:https://kubernetes.io/zh/ Kubernetes是谷歌十几年大规模容器管理经验的成果 是 ...

  8. CCNA 之 六 路由协议 二 EIGRP

    EIGRP(Enhanced IGRP) 增强型内部网关路由协议 注意:这是cisco私有协议:也就是说,该协议只能运行在思科的设备上,如果有其他的厂家的设备,则不能保证能运行此协议: EIGRP的特 ...

  9. CCNA 之 十二 Frame Relay 帧中继

    Fram Relay 帧中继 帧中继简介 VC.LMI.DLCI的概念 帧中继映射 Inverse-ARP的操作 帧中继配置 帧中继简介 分组交换广域网接入方式的一个代表,分组交换是以分组的形式在广域 ...

  10. java程序员面试宝典之——Java 基础部分(1~10)

    基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".java"源文件中是否可以包 ...