AutoMQ 中的元数据管理

news2024/9/21 10:29:52

本文所述 AutoMQ 的元数据管理机制均基于 AutoMQ Release 1.1.0 版本 [1]。

01

前言

AutoMQ 作为新一代基于云原生理念重新设计的 Apache Kafka 发行版,其底层存储从传统的本地磁盘替换成了以对象存储为主的共享存储服务。对象存储为 AutoMQ 带来可观成本优势的同时,其与传统本地磁盘的接口和计费方式的差异也为 AutoMQ 在实现上带来了挑战,为解决这一问题,AutoMQ 基于 KRaft 进行拓展,实现了一套针对对象存储环境的流存储元数据管理机制,在兼顾成本的同时,极大的保证了基于对象存储的读写性能。

02

AutoMQ 需要哪些元数据

KV 元数据

在之前的文章中(AutoMQ 如何做到 Apache Kafka 100% 协议兼容 [2]),我们介绍过了 AutoMQ 的存储层如何基于 S3Stream [3] 实现对对象存储服务的流式读写的,每个分区都有与之对应的多个 Stream 来分别负责存储分区的元数据、消息、Time Index、Txn Index 等。AutoMQ 通过 KV 元数据来保存分区所对应的 MetaStream 的 StreamId,从而保证分区在不同节点打开时都能正确获得与 Stream 的映射关系。

Stream 元数据

由于分区和 Stream 有着一对多的映射关系,当分区发生迁移、数据写入、位点 Trim 等事件时,其对应的 Stream 状态也会相应发生变化。因此 AutoMQ 对每个 Stream 都维护了相应的元数据,主要由以下部分组成:

  • Stream Epoch:当分区发生迁移时,会提升对应的 Stream Epoch,后续所有对 Stream 的操作都需要对 Epoch 进行检查,保证只有 Stream 当前所在节点能够对 Stream 进行操作

  • Start Offset:用于表示 Stream 的起始位点,当分区发生 Trim 时,其对应的 Stream 的起始位点也会被相应更新

  • End Offset:用于表示 Stream 的最大位点,当分区消息成功写入并提交后,Stream 的最大位点也会相应推进

  • Ranges:随着分区的迁移,Stream 也会在不同的节点上产生数据,Ranges 保存着 Stream 在各个节点打开期间的位点变化,在后文中会具体介绍 Ranges 的作用

  • StreamObjects:用于保存 Stream 对应的 StreamObject 的 ObjectId,以及在相应 Object 上的位点范围

每当 Controller 接收到 Stream 的相关操作时(如 create, open, commit, trim 等),都会产生相应的 S3StreamRecord,通过 KRaft 层持久化后将状态更新到内存中,并同步更新到各个 Broker 的元数据缓存。

Node 元数据

Node 元数据由以下部分组成:

  • Node Id:即节点 Id

  • Node Epoch:即节点 Epoch,与 Stream Epoch 作用类似,当节点发生重启时会提升相应的 Node Epoch,来保证只有带有最新 Epoch 的节点能够进行 Stream 相关操作

  • Failover Mode:用于标识当前节点是否处在 Failover 模式(关于 AutoMQ 的 Failover 能力会在后续的文章中介绍)

  • StreamSetObjects:用于保存当前节点产生的各个 StreamSetObject,以及各 Object 上不同 Stream 的位点索引信息

其中, Node Epoch 及 Failover Mode 会在节点首次启动时,通过 open streams 接口产生一条 NodeWALMetadataRecord 来进行更新,而 StreamSetObjects 则会在节点向 Controller 提交 StreamSetObject 时通过 S3StreamSetObjectRecord 更新。

Object 元数据

Object 元数据负责所有对象存储对象的生命周期管理,包括对象的状态、大小、Key、过期时间、提交时间、标记删除时间等。

03

整体流程

本节将介绍 AutoMQ 如何在各个阶段利用上述介绍的元数据实现对对象存储的高效利用。

分区打开

分区打开时,节点会先向 Controller 请求该分区对应的 MetaStream Id,若 MetaStream 不存在,则表示该分区为首次创建,此时节点会为该分区创建一个 MetaStream 并将分区到 MetaStream 的映射关系发送给 Controller,Controller 收到后根据 Key 和 Value 创建出 KVRecord,通过 KRaft 层持久化后将 KV 映射关系写入内存中。若 MetaStream 存在,则从 MetaStream 中读取出分区各 Segment 对应的 Stream 的信息,从而能够使得后续对分区的读写能够正确转换为对 Stream 的读写。

分区数据写入

所有针对分区的写入通过上述 MetaStream 中解析出的映射关系,最终都会转变为对 Stream 的写入,而所有 Stream 写入的数据都会首先写入 EBS WAL,持久化成功后直接向上层返回结果;同时写入的数据会继续在内存中进行混合攒批,直到攒批大小超过阈值时触发上传。上传触发后,节点会遍历此次攒批的数据中的各个 Stream,将连续数据段超过一定阈值大小的上传为 StreamObject,剩余数据上传为 StreamSetObject。每个 Object 上传时,节点会先向 Controller 申请全局唯一的 Object Id,此时 Controller 的 Object 元数据中会记录下该 Object 的状态和过期时间,节点通过 Object Id 生成对象存储的写入路径并上传数据。当本次上传任务产生的所有 Object 全部写入完成后,节点会向 Controller 发起 Commit 请求,Controller 将产生一系列 KRaft Record 更新元数据:

  • Object 元数据:将此次提交的 Object 状态从 PREPARED 置为 COMMITTED

  • Stream 元数据:推进此次提交的批数据中的各 Stream 最大位点,以及更新 Stream 对应的 StreamObjects

  • Node 元数据:更新对应节点的 StreamSetObjects

若在上传过程中,节点发生异常导致上传终止,Controller 则会通过定时任务将超出过期时间依旧未提交的 Object 删除,以避免对象泄漏。

分区数据读取

分区数据的读取同样会转换为对 Stream 的读取,当需要读取的数据段已不再存在于节点缓存中时,就需要向对象存储发起读取,而通过上文介绍的分区写入流程,我们已经知道元数据中已经保存了 Stream 各数据段所在的 Object,此时只需从元数据中索引出需要读取的数据段对应的 Object 列表,再向对象存储发起读取请求即可。这里需要注意的是,由于 AutoMQ 的元数据全部基于 KRaft 机制构建,故上述的元数据变更全部会跟随 KRaft Record 的同步而分发到每台节点上,也即每台 Broker 都缓存有最新的元数据信息,所以索引的过程全部发生在本地缓存中。具体的索引流程如下:

  1. 首先从本地的 Stream 元数据缓存中获取 Stream 对应的 StreamObjects,由于每一个 StreamObject 都对应着 Stream 的一个连续数据段,此时只需从第一个 StreamObject 开始遍历,并将满足范围的加入到结果中,直到遇到第一个超出期望读取的数据范围的 StreamObject,或所有 StreamObject 都已被遍历完毕。

  2. 当对 StreamObject 的遍历退出后,若此时还未满足期望的读取范围,则意味着接下来的数据存在于 StreamSetObject 中,从上述元数据介绍中我们知道,Stream 元数据中记录了 Ranges 信息,其对应着 Stream 在不同节点上的位点范围。而 Ranges 是一个按位点顺序排列的有序列表,此时只需通过一次二分查找即可找到当前期望数据段所在的 Range,和对应 Range 所在的 Node Id。

  3. 找到 Node Id 后即可在 Node 元数据中获取该 Node 对应的 StreamSetObejcts,而每个 StreamSetObject 中都保存了组成该 Object 的各 Stream 的位点信息,此时对 StreamSetObjects 进行一次遍历,即可获得符合当前期望数据段的 StreamSetObject。

  4. 当 StreamSetObjects 遍历完成后,可能依旧存在期望读取的数据还未得到满足的情况,此时会再次进入步骤 1,从上次一的 StreamObject 遍历点开始继续下一轮搜索,直到请求范围得到满足;或因为元数据同步延迟等原因,所有 Object 均遍历完毕依旧没能满足请求,此时会直接将部分满足的请求返回,等待下次请求重试。

可以看到,由于 StreamSetObject 构成的复杂性,索引的大多数成本花费在了对 StreamSetObject 的搜索中,为提升索引速度,AutoMQ 还额外实现了 Compaction 机制,能够使得 Stream 的大多数数据都存在于 StreamObject 中(感兴趣的读者可参考:AutoMQ 对象存储数据高效组织的秘密: Compaction [4])。

04

总结

本文介绍了 AutoMQ 基于 KRaft 的元数据管理机制,相比传统基于 Zookeeper 的元数据管理,Controller 由于成为了所有元数据的处理节点,其稳定性对系统的正常运行起到了至关重要的作用,而 AutoMQ 在进一步拓展了对象存储相关的元数据后,对 Controller 节点的稳定性也提出了更高的要求。为此,AutoMQ 团队也在持续优化元数据规模和索引效率,保障在单一超大规模集群下的高效稳定运行。

参考资料

[1] AutoMQ Release 1.1.0:https://github.com/AutoMQ/automq/releases/tag/1.1.0
[2] AutoMQ 如何做到 Apache Kafka 100% 协议兼容:https://mp.weixin.qq.com/s/ZOTu5fA0FcAJlCrCJFSoaw [3] S3Stream: A Shared Streaming Storage Library:https://github.com/AutoMQ/automq/tree/main/s3stream
[4] AutoMQ 对象存储数据高效组织的秘密: Compaction:https://mp.weixin.qq.com/s/z_JKxWQ8YCMs-fbC42C0Lg

关于我们

我们是来自 Apache RocketMQ 和 Linux LVS 项目的核心团队,曾经见证并应对过消息队列基础设施在大型互联网公司和云计算公司的挑战。现在我们基于对象存储优先、存算分离、多云原生等技术理念,重新设计并实现了 Apache Kafka 和 Apache RocketMQ,带来高达 10 倍的成本优势和百倍的弹性效率提升。

🌟 GitHub 地址:https://github.com/AutoMQ/automq
💻 官网:https://www.automq.com?utm_source=openwrite

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1927781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基坑安全:自动化监测系统的革新力量

在日新月异的基坑工程领域,基坑安全自动化监测系统犹如一位守护者,以其独特的优势,为工程的安全与质量保驾护航。该系统集先进的测量仪器、计算机技术与现代传感技术于一体,对基坑的围护结构及周边环境进行全方位、高精度的实时监…

OpenGL笔记一之基础窗体搭建以及事件响应

OpenGL笔记一之基础窗体搭建以及事件响应 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记一之基础窗体搭建以及事件响应1.运行2.目录结构3.main.cpp4.CMakeList.txt 1.运行 2.目录结构 01_GLFW_WINDOW/ ├── CMakeLists.txt ├── glad.c ├── ma…

机器人及其相关工科专业课程体系

机器人及其相关工科专业课程体系 前言传统工科专业机械工程自动化/控制工程计算机科学与技术 新兴工科专业智能制造人工智能机器人工程 总结Reference: 前言 机器人工程专业是一个多领域交叉的前沿学科,涉及自然科学、工程技术、社会科学、人文科学等相关学科的理论…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】 本地事务事务的基本性质事务的隔离级别(下面四个越往下,隔离级 别越高,并发能力越差)事务的传播行为(是否…

花几千上万学习Java,真没必要!(七)

swtich语句: 测试代码1: package testswitch.com;//根据月份和年份,当月份是 2 时,检查年份是否为闰年,然后继续执行下一个 case,打印出"三月",然后终止switch 语句。 public class …

微软Edge浏览器深度解析:性能、安全性与特色功能全面评测

一、引言 自Windows 10操作系统推出以来,微软Edge浏览器作为默认的网页浏览器,凭借其现代化的设计和出色的性能表现,逐渐获得了用户的认可。本文旨在对Edge浏览器进行深入分析,探讨其在多个方面的表现。 二、界面与操作体验 界面…

力扣每日一题:807. 保持城市天际线

文章目录 ***今日份每日一题:***题目要求:示例如下:示例1示例2 解释剖析示例示例1示例2 将逻辑思路转换为代码 力扣官网:前往作答!!!! 今日份每日一题: 题目要求&#…

算法-二叉树常见问题详解

文章目录 1. 二叉树的三种遍历方式的实质2. 二叉树的序列化与反序列化3. 根据前序中序反序列创建二叉树4. 二叉树的路径问题5. LCA公共祖先问题6. 二叉搜索树的LCA问题7. 验证搜索二叉树8. 修建搜索二叉树9. 二叉树打家劫舍问题 1. 二叉树的三种遍历方式的实质 这个相信大家都不…

Python从0到100(四十):Web开发简介-从前端到后端(文末免费送书)

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

王权与自由steam服测试资格申请 王权与自由国际服测试资格申请

不少人都开始期待《王权与自由国际服》的内测,消息已经传出,这款游戏的内测马上会在 太平洋时间4月10日下午1点,也就是世界标准时间的晚上8点,开始封闭式Beta测试,测试时间有为一周,持续到4月17日的太平洋…

万字长文之分库分表里如何设计一个主键生成算法?【后端面试题 | 中间件 | 数据库 | MySQL | 分库分表】

分库分表是在面试里一个非常热门而且偏难的话题,下面了解UUID、自增主键和雪花算法的特点,并且在面试的时候刷出亮点。 前置 所谓的分库分表严格来说是分数据源、分库和分表。例如每个公司订单表的分库分表策略就是用了8个主从集群,每个主从…

Layout View

GoTo 数据网格和视图入门 本文档仅概述特定于LayoutView的功能。有关常用卡和选择功能的信息,请参阅根卡和布局视图一文。 Template Card 布局视图使用布局控件来排列卡片内的内容。对于每个网格列,都会生成一个LayoutViewField对象。切换到数据网格设…

django超市管理系统-计算机毕业设计源码53507

摘 要 随着社会经济的不断发展,超市作为零售行业的一部分,扮演着重要的角色。在信息技术的快速发展的背景下,计算机软件和硬件技术的普及应用在商业管理中起到了至关重要的作用,因此基于Django的超市管理系统应运而生,…

昇思25天学习打卡营第15天|基于MobileNetv2的垃圾分类

一、关于MobileNetv2 MobileNet网络专注于移动端、嵌入式或IoT设备的轻量级CNN网络。MobileNet网络使用深度可分离卷积(Depthwise Separable Convolution)的思想在准确率小幅度降低的前提下,大大减小了模型参数与运算量。并引入宽度系数 α和…

MySQL集群、Redis集群、RabbitMQ集群

一、MySQL集群 1、集群原理 MySQL-MMM 是 Master-Master Replication Manager for MySQL(mysql 主主复制管理器)的简称。脚本)。MMM 基于 MySQL Replication 做的扩展架构,主要用来监控 mysql 主主复制并做失败转移。其原理是将真…

解决vscode项目中无法识别宏定义的问题

在c_cpp_properties.json中的"defines":[]中定义的宏无法被识别。 从而导致代码中的宏开关无法生效,造成代码的阅读不便利。 排查路线是: 关闭所有插件,删除当前工程目录下的.vscode文件夹。 经过一系列排查发现是C/C插件与clangd插…

能把进程和线程讲的这么透彻的,没有20年功夫还真不行【0基础也能看懂】

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…

数据库基本查询(表的增删查改)

一、增加 1、添加信息 insert 语法 insert into table_name (列名) values (列数据1,列数据2,列数据3...) 若插入时主键或唯一键冲突就无法插入。 但如果我们就是要修改一列信息也可以用insert insert into table_name (列名) values (列数据1&am…

nginx的正向与反向代理

正向代理与反向代理的区别 虽然正向代理和反向代理都涉及代理服务器接收客户端请求并向服务端转发请求,但它们之间存在一些关键的区别: 正向代理: 在正向代理中,代理服务器代表客户端向服务器发送请求,并将服务…

【Linux】安装PHP扩展-igbinary

说明 本文档是在centos7.6的环境下,安装PHP7.4之后,安装对应的PHP扩展igbinary。 一、igbinary简述 igbinary 是一个 PHP 扩展,主要用于序列化和反序列化数据,其设计目的是为了提高序列化过程中的性能和内存效率。 优点&#…