重新理解 RocketMQ Commit Log 存储协议
最近突然感觉:很多软件、硬件在设计上是有 root reason 的,不是 by desgin 如此,而是解决了那时、那个场景的那个需求。一旦了解后,就会感觉在和设计者对话,了解他们的思路,学习他们的方法,思维同屏:活到老学到老。
问题思考
1、Consumer Queue Offset 是连续的吗, 为什么?
2、Commit Log Offset 是连续的吗, 为什么?
3、Java 写的文件,默认是大端序还是小端序,为什么?
Commit Log 真实分布
在大家思考之际, 我们回想下 commit log 是怎么分布的呢?
在 Broker 配置的存储根目录下,通过查看 Broker 实际生成的 commit log 文件可以看到类似下面的数据文件分布:
可以看到,真实的存储文件有多个, 每一个都是以一串类似数字的字符串作为文件名的,并且大小 1G。
我们结合源码可以知道,实际的抽象模型如下:
由上图得知:
Commit Log 是一类文件的称呼,实际上 Commit Log 文件有很多个, 每一个都可以称为 Commit Log 文件。如图中表示了总共有 T 个 Commit Log 文件,他们按照由过去到现在的创建时间排列。
每个 Commit Log 文件都保存消息, 并且是按照消息的写入顺序保存的,并且总是在写创建时间最大的文件,并且同一个时刻只能有一个线程在写。如图中第 1 个文件,1,2,3,4... 表示这个文件的第几个消息,可以看到第 1234 个消息是第 1 个 Commit Log 文件的最后一个消息,第 1235 个消息是第 2 个 Commit Log 的第 1 个消息。
说明 1:每个 Commit Log 文件里的全部消息实际占用的存储空间大小 <=1G。这个问题大家自行思考下原因。
说明 2:每次写 Commit Log 时, RocketMQ 都会加锁,代码片段见 https://github.com/apache/rocketmq/blob/7676cd9366a3297925deabcf27bb590e34648645/store/src/main/java/org/apache/rocketmq/store/CommitLog.java#L676-L722
我们看到 Commit Log 文件中有很多个消息,按照既定的协议存储的,那具体协议是什么呢, 你是怎么知道的呢?
Commit Log 存储协议
关于 Commit Log 存储协议,我们问了下 ChatGPT, 它是这么回复我的,虽然不对,但是这个回复格式和说明已经非常接近答案了。
我们翻看源码,具体说明下:https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.3/store/src/main/java/org/apache/rocketmq/store/CommitLog.java#L1547-L1587
我整理后, 如下图:
说明 1:我整理后的消息协议编号和代码中不是一致的,代码中只是标明了顺序, 真实物理文件中的存储协议会更详细。说明 2:在我写的《RocketMQ 分布式消息中间件:核心原理与最佳实践》中,这个图缺少了 Body 内容,这里加了,也更详细的补充了其他数据。 这里有几个问题需要说明下:
1、二进制协议存在字节序,也就是常说的大端、小端。大小端这里不详细说明感兴趣的同学自己 google 或者问题 ChatGPT,回答肯定比我说的好。
2、在 java 中, 一个 byte 占用 1 个字节,1 个 int 占用 4 个字节,1 个 short 占用 2 个字节,1 个 long 占用 8 个字节。
3、Host 的编码并不是简单的把 IP:Port 作为字符串直接转化为 byte 数组,而是每个数字当作 byte 依次编码。在下一节的 Golang 代码中会说明。
4、扩展信息的编码中,使用了不可见字符作为分割,所以扩展字段 key-value 中不能包含那 2 个不可见字符。具体是哪 2 个,大家找找?
我们看到这个协议后,如何证明你的物理文件就是按照这个协议写的呢?
用 Golang 解开 RocketMQ Commit Log
RocketMQ 是用 java 写的,根据上文描述的存储协议,我用 Golang 编写了一个工具,可以解开 Commit Log 和 Cosumer Queue,代码地址:https://github.com/rmq-plus-plus/rocketmq-decoder。
这个工具目前支持 2 个功能:
1、指定 Commit Log 位点,直接解析 Commit Log 中的消息,并且打印。
2、指定消费位点,先解析 Consumer Queue,得到 Commit Log Offset 后,再根据 Commit Log Offset 直接解析 Commit Log,并且打印。
在 Golang 中没有依赖 RocketMQ 的任何代码,纯粹是依靠协议解码。
这里贴了一段 golang 中解析 Commit Log Offset 的例子:在 java 中这个 offset 是一个 long 类型,占用 8 个字节。
在 golang 中,读取 8 个字节长度的数据,并且按照大端序解码为 int64,就可以得到正常的 Commit Log Offset。
我跑了一个 demo 结果,大家参考:
回答最初的问题
以下为个人见解,大家参考:
1、Consumer Queue Offset 是连续的吗, 为什么?
是连续的。
consumer queue offset,是指每个 queue 中索引消息的下标,下标当然是连续的。消费者也是利用了这个连续性,避免消费位点提交空洞的。
每个索引消息占用相同空间,都是 20 字节,结构如下:
这里物理位点也就是 Commit Log Offset。
2、Commit Log Offset 是连续的吗, 为什么?
不是连续的。
Commit Log Offset 是指的每个消息在全部 Commit Log 文件中的字节偏移量, 每个消息的大小是不确定的,所以 Commit Log Offset,也即是字节偏移量肯定是不一样的。
并且可以知道,每两个偏移量的差的绝对值就是前一个消息的消息字节数总长度。
并且上文中图 “Commit Log 存储文件分布抽象” 中的有误解,每个小方格的大小其实是不一样的。
3、Java 写的文件,默认是大端序还是小端序,为什么?
大端序。大端序其实有字节存储顺序和网络传输顺序,java 中默认用的大端序,保持和网络传输一样,这样方便编解码。
每段网络传输层的数据报文最前面的字节是表达后面的数据是用什么协议传输的,这样数据接收者在接受数据时, 按照字节顺序,先解析协议,再根据协议解码后面的字节序列,符合人类思考和解决问题的方式。
讨论说明:由于 RocketMQ 一些版本可能有差异,本文在 4.9.3 版本下讨论,大家可以参考这个方法,解开
5.0 甚至其他版本,其他数据文件的存储协议格式。
相关文章:

重新理解 RocketMQ Commit Log 存储协议
最近突然感觉:很多软件、硬件在设计上是有 root reason 的,不是 by desgin 如此,而是解决了那时、那个场景的那个需求。一旦了解后,就会感觉在和设计者对话,了解他们的思路,学习他们的方法,思维…...

ES6基础知识十:你是怎么理解ES6中 Decorator 的?使用场景?
一、介绍 Decorator,即装饰器,从名字上很容易让我们联想到装饰者模式 简单来讲,装饰者模式就是一种在不改变原类和使用继承的情况下,动态地扩展对象功能的设计理论。 ES6中Decorator功能亦如此,其本质也不是什么高大…...

接口/Web自动化测试如何做?框架如何搭建封装?
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 自动化测试怎么做…...
Linux怎么从网络上下载文件
wget命令用于从网络上下载文件 下载文件: wget [URL]使用wget命令加上要下载的文件的URL,可以将文件下载到当前目录。 指定保存的文件名: wget -O [保存的文件名] [URL]使用-O选项后跟保存的文件名,可以指定下载的文件保存的名称…...
Flutter携带JSON参数post请求
在Flutter中发送带有JSON参数的网络请求,你可以使用HTTP库(如http或dio)来实现。以下是使用http库发送网络请求并携带JSON参数的示例: import package:http/http.dart as http; import dart:convert;// 创建参数Map Map<Strin…...

【vue】vue-image-lazy图片懒加载使用与介绍【超详细+npm包源代码】
简介 当前插件是基于vue3,写的一个图片懒加载,文章最下方是npm包的源码,你可以自己拿去研究和修改,如有更好的想法可以留言,如果对你有帮助,可以点赞收藏和关注,谢谢。 后续会添加图片放大和切…...

MFC第二十四天 使用GDI对象画笔和画刷来开发控件(分页控件选择态的算法分析、使用CToolTipCtrl开发动静态提示)
文章目录 GDI对象画笔和画刷来开发控件梯形边框的按钮控件CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp 矩形边框的三态按钮控件 CToolTipCtrl开发动静态提示CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp: 实现文件 矩形边框的三态按钮控件 CToolTipCtrl开发动…...

【NLP-新工具】语音转文本与OpenAI的用途
一、说明 OpenAI最近2022发布了一个名为Whisper的新语音识别模型。与DALLE-2和GPT-3不同,Whisper是一个免费的开源模型。它的主要功能就是将语音翻译成文本。本文将介绍如何使用这个重要应用库。 二、 Whisper概念 2.1 Whisper是啥? Whisper 是一种自动…...
try-catch-finally的字节码原理
Java 中有一个非常重要的内容是 try-catch-finally 的执行顺序和返回值问题,其中 finally 一定会执行,但是为什么会这样? 下面看下 try-catch-finally 背后的实现原理 try-catch public class Test {public static void main(String[] args)…...

基于双层优化的微电网系统规划设计方法(Matlab代码实现)
目录 💥1 概述 1.1 微电网系统结构 1.2 微电网系统双层规划设计结构 1.3 双层优化模型 1.4 上层容量优化模型 1.5 下层调度优化模型 📚2 运行结果 🎉3 文献来源 🌈4 Matlab代码、数据、文章讲解 💥1 概述 文献来源&…...

【Nginx13】Nginx学习:HTTP核心模块(十)Types、AIO及其它配置
Nginx学习:HTTP核心模块(十)Types、AIO及其它配置 今天学习的内容也比较简单,主要的是 Types 相关的配置,另外还会了解一下 AIO 以及部分没有特别大的分类归属的配置指令的使用。后面的内容都是 HTTP 核心模块中比较小…...
2023年华数杯数学建模C题思路分析
文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor 1 竞赛信息 为了培养学生的创新意识及运用数…...

安卓手机变身Linux服务器
文章目录 前言一、准备工作1、安卓手机2、下载软件二、开始安装1、检查系统,确认版本并安装2、配置(安卓7.0 及以上的用户忽略此步)3、问题处理【没有异常的小伙伴忽略】总结前言 在实际开发中有很多地方都需要服务器资源,但是服务器资源不论在哪里都是比较紧缺的资源,今…...

【Ansible】Ansible自动化运维工具之playbook剧本
playbook 一、playbook 的概述1. playbook 的概念2. playbook 的构成 二、playbook 的应用1. 安装 httpd 并启动2. 定义、引用变量3. 指定远程主机 sudo 切换用户4. when条件判断5. 迭代6. Templates 模块6.1 添加模板文件6.2 修改主机清单文件6.3 编写 playbook 7. tags 模块 …...
Yolov8目标检测
Yolov8目标检测 目录 Yolov8目标检测一、准备数据集二、源码下载配置2.1 下载库2.2 修改配置2.3 训练2.4 验证2.5 测试2.6 模型导出2.7 本地测试 一、准备数据集 Yolov8只支持yolo格式的数据,所以,需要将数据集格式调整为 datasets|images|train|00000…...

Jmeter用于接口测试中,关联如何实现
Jmeter用于接口测试时,后一个接口经常需要用到前一次接口返回的结果,应该如何获取前一次请求的结果值,应用于后一个接口呢,拿一个登录的例子来说明如何获取。 1、打开jmeter, 使用的3.3的版本,新建一个测试计划&#x…...

线程状态
从卖包子的案例学习进程间的通信 public class Test {public static void main(String[] args) {Object objnew Object();Thread th1new Thread(){Overridepublic void run() {synchronized (obj){System.out.println("来三个包子!");try {obj.wait(); /…...

HTML一些基础知识
1、Web标准:主要包含结构、表现、行为。结构用于对网页元素进行整理和分类,主要指HTML。表现用于设置网页元素的板式、颜色、大小等外观样式,主要指的是CSS。行为主要指的是网页模型的定义以及交互的编写,主要是js文件。 Html相当…...
git 命令总结
一、本地分支和仓库里的分支不同步(本地看不到最新的分支) 1.使用 git fetch origin 或者git remote update origin --prune命令更新 2.git branch -r 查看 即可 二、git 合并代码 1. git 如何把分支代码合并到master 1.1 首先切换到分支 git checkou…...
【Django】如何优化数据库访问
原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、数据库层面优化常用优化postgresql查询分库分表 二、内存层面优化三、代码层面优化 前言 Django是一个高级的Web框架,它…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...

智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...
学习 Hooks【Plan - June - Week 2】
一、React API React 提供了丰富的核心 API,用于创建组件、管理状态、处理副作用、优化性能等。本文档总结 React 常用的 API 方法和组件。 1. React 核心 API React.createElement(type, props, …children) 用于创建 React 元素,JSX 会被编译成该函数…...

Qt 按钮类控件(Push Button 与 Radio Button)(1)
文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button(鼠标点击不放连续移动快捷键) Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...

AI书签管理工具开发全记录(十八):书签导入导出
文章目录 AI书签管理工具开发全记录(十八):书签导入导出1.前言 📝2.书签结构分析 📖3.书签示例 📑4.书签文件结构定义描述 🔣4.1. 整体文档结构4.2. 核心元素类型4.3. 层级关系4.…...

MySQL 数据库深度剖析:事务、SQL 优化、索引与 Buffer Pool
在当今数据驱动的时代,数据库作为数据存储与管理的核心,其性能与可靠性至关重要。MySQL 作为一款广泛使用的开源数据库,在众多应用场景中发挥着关键作用。在这篇博客中,我将围绕 MySQL 数据库的核心知识展开,涵盖事务及…...