@(本节目录)
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 多副本存储实现的更多相关文章

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

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

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

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

  3. 源码分析RocketMQ消息轨迹

    目录 1.发送消息轨迹流程 1.1 DefaultMQProducer构造函数 1.2 SendMessageTraceHookImpl钩子函数 1.3 TraceDispatcher实现原理 2. ...

  4. spark 源码分析之十八 -- Spark存储体系剖析

    本篇文章主要剖析BlockManager相关的类以及总结Spark底层存储体系. 总述 先看 BlockManager相关类之间的关系如下: 我们从NettyRpcEnv 开始,做一下简单说明. Ne ...

  5. 源码分析RocketMQ ACL实现机制

    目录 1.BrokerController#initialAcl 2.PlainAccessValidator 2.1 类图 2.2 构造方法 2.3 parse方法 2.4 validate 方法 ...

  6. 从源码分析RocketMq消息的存储原理

    rocketmq在存储消息的时候,最终是通过mmap映射成磁盘文件进行存储的,本文就消息的存储流程作一个整理.源码版本是4.9.2 主要的存储组件有如下4个: CommitLog:存储的业务层,接收& ...

  7. 基于 raft 协议的 RocketMQ DLedger 多副本日志复制设计原理

    目录 1.RocketMQ DLedger 多副本日志复制流程图 1.1 RocketMQ DLedger 日志转发(append) 请求流程图 1.2 RocketMQ DLedger 日志仲裁流程 ...

  8. RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)

    在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...

  9. spark源码分析以及优化

    第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...

随机推荐

  1. m98 lsc rp-- 赛

    lsc 这次又烧rp了! T1随机化艹spj 本机测试输出字符串长度没有低于1W的,考完发现凉凉 但是lemon又救了我的*命,垃圾lsc又烧rp了!

  2. 你真的会写单测吗?TDD初体验

    前言: 昨天读到了一篇文章,讲的是TDD,即Test-Driven Development,测试驱动开发.大体意思是,它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过 ...

  3. SpringBoot系列之@Conditional注解用法简介

    SpringBoot系列之@Conditional注解用法简介 引用Spring官方文档的说法介绍一下@Conditional注解:Spring5.0.15版本@Conditional注解官方文档 @ ...

  4. linux系统LAMP环境部署

    一.安装虚拟机 二.安装CentOS7 注意:以下安装,用的root权限. 三.安装Apache 1.安装 yum -y install httpd 2.开启apache服务 systemctl st ...

  5. ios遇到的坑

    总结体会:很多ios兼容性问题都是由于body设置了height:100% ios中input输入不了 在ios中margin属性不起作用 设置html body的高度为百分比时,margin-bot ...

  6. SpEL + AOP实现注解的动态赋值

    一.自定义注解 先聊聊这个需求,我需要根据用户的权限对数据进行一些处理,但是痛点在哪里呢?用户的权限是在请求的时候知道的,我怎么把用户的权限传递给处理规则呢?想了以下几种方案: Mybatis 拦截器 ...

  7. Java :一文掌握 Lambda 表达式

    本文将介绍 Java 8 新增的 Lambda 表达式,包括 Lambda 表达式的常见用法以及方法引用的用法,并对 Lambda 表达式的原理进行分析,最后对 Lambda 表达式的优缺点进行一个总 ...

  8. Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    前言 在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security.Apache Shiro 等.本文主要简单介绍一下 Spring Security,再通过 ...

  9. Oracle数据库 获取CLOB字段存储的xml格式字符串指定节点的值

    参照: Oracle存储过程中使用游标来批量解析CLOB字段里面的xml字符串 背景:在写存储过程时,需要获取表单提交的信息.表单信息是以xml格式的字符串存储在colb类型的字段dataxml中,如 ...

  10. Rust 入门 (一)

    Rust 语言的介绍.特性什么的都不说了,如有需要,请自行了解.这里我们直接进去正题. 一.开发环境 mac或linux系统,在命令行安装 curl https://sh.rustup.rs -sSf ...