源码分析 RocketMQ DLedger 多副本存储实现
目录
@(本节目录)
RocketMQ DLedger 的存储实现思路与 RocketMQ 的存储实现思路相似,本文就不再从源码角度详细剖析其实现,只是点出其实现关键点。我们不妨简单回顾一下 CommitLog 文件、ConsumeQueue 文件设计思想。
其文件组成形式如下:

正如上图所示,多个 commitlog 文件组成一个逻辑上的连续文件,使用 MappedFileQueue 表示,单个 commitlog 文件使用 MappedFile 表示。
温馨提示:如果想详细了解 RocketMQ 关于存储部分的讲解,可以关注笔者的《RocketMQ 技术内幕》一书。
1、DLedger 存储相关类图

1.1 DLedgerStore
存储抽象类,定义如下核心方法:
- public abstract DLedgerEntry appendAsLeader(DLedgerEntry entry)
 向主节点追加日志(数据)。
- public abstract DLedgerEntry appendAsFollower(DLedgerEntry entry, long leaderTerm, String leaderId)
 向从节点同步日志。
- public abstract DLedgerEntry get(Long index)
 根据日志下标查找日志。
- public abstract long getCommittedIndex()
 获取已提交的下标。
- public abstract long getLedgerEndTerm()
 获取 Leader 当前最大的投票轮次。
- public abstract long getLedgerEndIndex()
 获取 Leader 下一条日志写入的下标(最新日志的下标)。
- public abstract long getLedgerBeginIndex()
 获取 Leader 第一条消息的下标。
- public void updateCommittedIndex(long term, long committedIndex)
 更新commitedIndex的值,为空实现,由具体的存储子类实现。
- protected void updateLedgerEndIndexAndTerm()
 更新 Leader 维护的 ledgerEndIndex 和 ledgerEndTerm 。
- public void flush()
 刷写,空方法,由具体子类实现。
- public long truncate(DLedgerEntry entry, long leaderTerm, String leaderId)
 删除日志,空方法,由具体子类实现。
- public void startup()
 启动存储管理器,空方法,由具体子类实现。
- public void shutdown()
 关闭存储管理器,空方法,由具体子类实现。
1.2 DLedgerMemoryStore
Dledger 基于内存实现的日志存储。
1.3 DLedgerMmapFileStore
基于文件内存映射机制的存储实现。其核心属性如下:
- long ledgerBeginIndex = -1
 日志的起始索引,默认为 -1。
 l- ong ledgerEndIndex = -1
 下一条日志下标,默认为 -1。
- long committedIndex = -1
 已提交的日志索引。
- long ledgerEndTerm
 当前最大的投票轮次。
- DLedgerConfig dLedgerConfig
 DLedger 的配置信息。
- MemberState memberState
 状态机。
- MmapFileList dataFileList
 日志文件(数据文件)的内存映射Queue。
- MmapFileList indexFileList
 索引文件的内存映射文件集合。(可对标 RocketMQ MappedFIleQueue )。
- ThreadLocal< ByteBuffer> localIndexBuffer
 本地线程变量,用来缓存索引ByteBuffer。
- ThreadLocal< ByteBuffer> localEntryBuffer
 本地线程变量,用来缓存数据索引ByteBuffer。
- FlushDataService flushDataService
 数据文件刷盘线程。
- CleanSpaceService cleanSpaceService
 清除过期日志文件线程。
- boolean isDiskFull = false
 磁盘是否已满。
- long lastCheckPointTimeMs
 上一次检测点(时间戳)。
- AtomicBoolean hasLoaded
 是否已经加载,主要用来避免重复加载(初始化)日志文件。
- AtomicBoolean hasRecovered
 是否已恢复。
2、DLedger 存储 对标 RocketMQ 存储
存储部分主要包含存储映射文件、消息存储格式、刷盘、文件加载与文件恢复、过期文件删除等,由于这些内容在 RocketMQ 存储部分都已详细介绍,故本文点到为止,其对应的参考映射如下:

在 RocketMQ 中使用 MappedFile 来表示一个物理文件,而在 DLedger 中使用 DefaultMmapFIle 来表示一个物理文件。
在 RocketMQ 中使用 MappedFile 来表示多个物理文件(逻辑上连续),而在 DLedger 中则使用MmapFileList。
在 RocketMQ 中使用 DefaultMessageStore 来封装存储逻辑,而在 DLedger 中则使用DLedgerMmapFileStore来封装存储逻辑。
在 RocketMQ 中使用 Commitlog$FlushCommitLogService 来实现 commitlog 文件的刷盘,而在 DLedger 中则使用DLedgerMmapFileStore$FlushDataService来实现文件刷盘。
在 RocketMQ 中使用 DefaultMessageStore$CleanCommitlogService 来实现 commitlog 过期文件的删除,而 DLedger 中则使用 DLedgerMmapFileStore$CleanSpaceService来实现。
由于其实现原理相同,上述部分已经在《RocketMQ 技术内幕》第4章中详细剖析,故这里就不重复分析了。
3、DLedger 数据存储格式

存储格式字段的含义如下:
- magic
 魔数,4字节。
- size
 条目总长度,包含 Header(协议头) + 消息体,占4字节。
- entryIndex
 当前条目的 index,占8字节。
- entryTerm
 当前条目所属的 投票轮次,占8字节。
- pos
 该条目的物理偏移量,类似于 commitlog 文件的物理偏移量,占8字节。
- channel
 保留字段,当前版本未使用,占4字节。
- chain crc
 当前版本未使用,占4字节。
- body crc
 body 的 CRC 校验和,用来区分数据是否损坏,占4字节。
- body size
 用来存储 body 的长度,占4个字节。
- body
 具体消息的内容。
源码参考点:DLedgerMmapFileStore#recover、DLedgerEntry、DLedgerEntryCoder。
4、DLedger 索引存储格式

即一个索引条目占32个字节。
5、思考
DLedger 存储相关就介绍到这里,为了与大家增加互动,特提出如下两个思考题,欢迎与作者互动,这些问题将在该系列的后面文章专题探讨。
1、DLedger 如果整合 RocketMQ 中的 commitlog 文件,使之支持多副本?
2、从老版本如何升级到新版本,需要考虑哪些因素呢?
尊敬的读者朋友们,都阅读到这里了,麻烦帮忙点个赞鼓励一下我,谢谢。
作者介绍:丁威,《RocketMQ技术内幕》作者,RocketMQ 社区布道师,公众号:中间件兴趣圈 维护者,目前已陆续发表源码分析Java集合、Java 并发包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等源码专栏。可以点击链接加入中间件知识星球 ,一起探讨高并发、分布式服务架构,交流源码。
源码分析 RocketMQ DLedger 多副本存储实现的更多相关文章
- 源码分析 RocketMQ DLedger(多副本) 之日志复制(传播)
		目录 1.DLedgerEntryPusher 1.1 核心类图 1.2 构造方法 1.3 startup 2.EntryDispatcher 详解 2.1 核心类图 2.2 Push 请求类型 2. ... 
- 源码分析 RocketMQ DLedger 多副本之 Leader 选主
		目录 1.DLedger关于选主的核心类图 1.1 DLedgerConfig 1.2 MemberState 1.3 raft协议相关 1.4 DLedgerRpcService 1.5 DLedg ... 
- 源码分析RocketMQ消息轨迹
		目录 1.发送消息轨迹流程 1.1 DefaultMQProducer构造函数 1.2 SendMessageTraceHookImpl钩子函数 1.3 TraceDispatcher实现原理 2. ... 
- spark 源码分析之十八 -- Spark存储体系剖析
		本篇文章主要剖析BlockManager相关的类以及总结Spark底层存储体系. 总述 先看 BlockManager相关类之间的关系如下: 我们从NettyRpcEnv 开始,做一下简单说明. Ne ... 
- 源码分析RocketMQ ACL实现机制
		目录 1.BrokerController#initialAcl 2.PlainAccessValidator 2.1 类图 2.2 构造方法 2.3 parse方法 2.4 validate 方法 ... 
- 从源码分析RocketMq消息的存储原理
		rocketmq在存储消息的时候,最终是通过mmap映射成磁盘文件进行存储的,本文就消息的存储流程作一个整理.源码版本是4.9.2 主要的存储组件有如下4个: CommitLog:存储的业务层,接收& ... 
- 基于 raft 协议的 RocketMQ DLedger 多副本日志复制设计原理
		目录 1.RocketMQ DLedger 多副本日志复制流程图 1.1 RocketMQ DLedger 日志转发(append) 请求流程图 1.2 RocketMQ DLedger 日志仲裁流程 ... 
- RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)
		在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ... 
- spark源码分析以及优化
		第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ... 
随机推荐
- HashMap 中的容量与扩容实现,细致入微,值的一品!
			前言 开心一刻 巴闭,你的脚怎么会有味道,我要闻闻看是不是好吃的,嗯~~爸比你的脚臭死啦!! …… 高手过招,招招致命 JDK1.8 中 HashMap 的底层实现,我相信大家都能说上来个 一二,底层 ... 
- PHP file_get_contents 读取js脚本的问题
			PHP file_get_contents 读取js脚本的问题 如果文件中带有js脚本 会触发 比方说alert 这个时候 你不用去管他 
- node.js评论列表和添加购物车数据库表创建
			2.1:评论列表--发表评论 用户点击新闻列表某一条新闻,看到新闻详细发表评论 -用户输入评论内容 -发表评论 [将用户评论内容保存数据库 xz_comment] 2.2:评论列表--发表评论-开发评 ... 
- java多线程与线程并发一:线程基础回顾
			本文章内容整理自:张孝祥_Java多线程与并发库高级应用视频教程 线程简单来讲就是程序正在做的事情.多线程即一个程序同时做多件事情,一个线程就是一件事情. 在java中创建线程的方法有两种. 方法一是 ... 
- C++中对C的扩展学习新增语法——动态内存管理
			1.C语言动态内存管理的缺点: 1.malloc对象的大小需要自己计算. 2.需要手动转换指针类型. 3.C++的对象不适合使用malloc和free. 2.C++中new/delete基本使用: 3 ... 
- logback日志回顾整理--2018年8月8日
			几年前使用过logback作为项目的日志框架. 当时觉得这个框架比log4j更加好用. 所以系统的学习了一遍. 后来换了公司, 不再使用logback. 如今, 又有机会使用logback了, 所以, ... 
- 【阿里巴巴-高德-汽车事业部】【内推】Java技术专家、前端技术专家、C++技术专家(长期招聘)
			简历接收邮箱:yx185737@alibaba-inc.com 邮件请备注来自CSDN 一.Java技术专家 职位描述 研究汽车智能化和在线服务前沿技术,从事在线数据服务和车联网服务的设计和研发 负责 ... 
- HTML建立超链接
			链接是HTML文档的最基本特征之一.超文本链接英文名为hyperlink,它能够让浏览器在各个独立的页面之间方便地跳转.超链接有外部链接.电子邮件链接.锚点链接等. a标签 网页中<a& ... 
- mysql的属性zerofill
			一.字段中zerofill属性的类似定义方式 SQL语句:字段名 int(M) zerofill 二.zerofill属性的作用 1.插入数据时,当该字段的值的长度小于定义的长度时,会在该值的前面补上 ... 
- J.U.C剖析与解读1(Lock的实现)
			J.U.C剖析与解读1(Lock的实现) 前言 为了节省各位的时间,我简单介绍一下这篇文章.这篇文章主要分为三块:Lock的实现,AQS的由来(通过演变的方式),JUC三大工具类的使用与原理剖析. L ... 
