AutoMQ 中的元数据管理

本文所述 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】初识C++(下)

前言 本篇博客继续总结一下C入门的一些小知识 💓 个人主页:小张同学zkf ⏩ 文章专栏:C 若有问题 评论区见📝 🎉欢迎大家点赞👍收藏⭐文章 ​ 目录 1.引用 1.1引用的概念 1.2const引用 1.3指针和引用的…

外包干了1个月,技术明显退步。。。

有一种打工人的羡慕,叫做“大厂”。 真是年少不知大厂香,错把青春插稻秧。 但是,在深圳有一群比大厂员工更庞大的群体,他们顶着大厂的“名”,做着大厂的工作,还可以享受大厂的伙食,却没有大厂…

软件测试面试题全网独家没有之一的资深测试工程师面试题集锦

1.自我介绍? 我是谁、工作几年、你上家公司做什么、负责什么、你的优势、为什么适合这个职位、我想做什么、在这个职位上想得到什么 有自信、不能吞吞吐吐 时间长度2-3分钟 2编写测试用例有哪几种方法? 等价类、边界值、因果图、流程分析、错误分析、…

【Pytorch】数据集的加载和处理(一)

Pytorch torchvision 包提供了很多常用数据集 数据按照用途一般分为三组:训练(train)、验证(validation)和测试(test)。使用训练数据集来训练模型,使用验证数据集跟踪模型在训练期间…

ectype:拓展ctype

拓展C库的ctype模块,将字节块或字符串进行分类或转换。

SQL Server 创建用户并授权

创建用户前需要有一个数据库,创建数据库命令如下: CREATE DATABASE [数据库名称]; CREATE DATABASE database1; 一、创建登录用户 方式1:SQL命令 命令格式:CREATE LOGIN [用户名] WITH PASSWORD 密码; 例如,创建…

全球DeepFake攻防挑战赛DataWhale AI 夏令营——图像赛道

全球DeepFake攻防挑战赛&DataWhale AI 夏令营——图像赛道 赛题背景 随着人工智能技术的迅猛发展,深度伪造技术(Deepfake)正成为数字世界中的一把双刃剑。这项技术不仅为创意内容的生成提供了新的可能性,同时也对数字安全构…

Mac 息屏不断网

这里息屏指的是屏幕不黑,屏幕黑了好像必断网 我的系统是 14.5 我调整了两个地方,一个是电池——选项——唤醒以供访问 另外一个地方是锁定屏幕——延长关闭显示器的时间(让显示器不黑)

如何批量删除重复数据?推荐两种方法

在日常的办公中,很多用户都会使用Excel。借助这款软件,用户可以完成对各种数据的处理。但很多时候我们会发现,同一张表格里有很多重复的数据,这或许会为统计带来错误。为此,我们就需要删除重复项才可以帮助我们很好的解…

STM32+三色LED智能调光系统源程序 易安卓APP 原理图

资料下载地址:STM32三色LED智能调光系统源程序 易安卓APP 原理图 三色LED手机智能调光系统概述: 利用开发的智能手机软件,对照明三色LED进行智能调光。包含的功能有,支持多手机同时连接服务端,互动调光。支持关…

前端Vue组件化实践:打造仿京东天猫商品属性选择器组件

在前端开发领域,随着业务需求的日益复杂和技术的不断进步,传统的整体式应用开发模式已逐渐显得捉襟见肘。面对日益庞大的系统,每次微小的功能修改或增加都可能导致整个逻辑结构的重构,形成牵一发而动全身的困境。为了解决这一问题…

昇思25天学习打卡营第22天|ResNet50图像分类

上回说到RESNET50做迁移学习,今天看一下他在图片分类上面的表现。图像分类是最基础的计算机视觉应用,属于有监督学习类别,先喂一堆猫的照片告诉他这是猫,再喂一堆狗的图片告诉他这是狗。 CIFAR-10数据集共有60000张32*32的彩色图…

ARDUINO最新pinMode()管脚设置方法(24年7月)

Arduino管脚配置 ESP32 Arduino管脚配置测试正常。 pinMode() [数字 I/O] 描述 将指定的引脚配置为输入或输出。有关引脚功能的详细信息,请参阅数字引脚部分。 可以使用模式INPUT_PULLUP使能内部上拉电阻。此外,INPUT模式明…

涨知识了!AI绘画变现的几个思路!

风口!风口!风口! 终于不用再抱怨 “我们这代人啊,什么也没赶上” 因为我们现在正处于风口之上! 在当今数字化的时代 AI 绘画正以惊人的速度崛起 并向各行各业渗透 既然阻止不了时代的变化 那就让它为我们所用 …

STM32MP135裸机编程:烧录程序到EMMC的方法

0 前言 STM32MP135支持多种启动方式,包括SD卡、NAND Flash、EMMC等,基于STM32MP135裸机的SD卡烧录操作方法我们之前已经介绍过,现在介绍的STM32MP135烧录到EMMC的方法又和前面烧录到SD卡的操作有所不同。本文将介绍基于STM32MP135&#xff0…

职称论文发表的注意事项有哪些

职称论文发表的注意事项有哪些 其实职称论文并不难,但是对于很多之前没有接触过的朋友来说,如何选择合适期刊,如何投稿以及版面费多少等一概不知。所以我今天就总结下我个人的经验,分享给大家。 一、弄清单位的要求 评职称论文首先…

系统架构师考点--软件工程(上)

大家好。今天我来总结一下软件工程的相关考点。这部分是考试的重点。在上午场客观题、下午场案例题以及下午场论文都有可能考到,在上午场客观题中大约占12-15分左右。 一、软件工程概述 软件开发生命周期 软件定义时期:包括可行性研究和详细需求分析过…

致良知,是一场自我革命、教育、成长

82天 【此亦须你自家求】人言不如自悔之真;致良知就是致自己,是一场自我革命、自我教育、自我成长;真诚的力量,诚于己、信于人、明于事 人言不如自悔之真,生活中我们都希望能够得到高人的指点,但&#xf…

Jmeter常用组件及执行顺序

一 常用组件 1.线程组 Thread Group 线程组是一系列线程的集合,每一个线程代表着一个正在使用应用程序的用户。在 jmeter 中,每个线程意味着模拟一个真实用户向服务器发起请求。 在 jmeter 中,线程组组件运行用户设置线程数量、初始化方式等…

git链接远程仓库

【 一 】ssh链接远程仓库 删除git仓库 【 1 】初步使用方法 1、之前把本地代码,以https形式,提交到了远程仓库 # - git remote add origin https://gitee.com/bai-zhitao/lufy.git- 输入用户名密码2、ssh认证,只需要配置一次&#xff…