作者:斜阳

RocketMQ 5.0 提出了分级存储的新计划,经过数个版本的深度打磨,RocketMQ 的分级存储日渐成熟,并成为下降存储本钱的重要特性之一。事实上,几乎一切涉及到存储的产品都会测验转冷降本,怎么针对音讯行列的业务场景去做一些有应战的技能优化, 是十分有意思的事。

这篇文章就跟大家讨论下,在音讯体系这样一个数据密集型运用的模型下,技能架构选型的分析与权衡,以及分级存储完结与未来演进,让云核算的资源盈利实在传达给用户。

背景与需求

RocketMQ 诞生于 2012 年,存储节点采用 shared-nothing 的架构读写自己的本地磁盘,单节点上不同 topic 的音讯数据会次序追加写 CommitLog 再异步构建多种索引,这种架构的高水平扩展才能和易保护性带来了十分强的竞赛力。

跟着存储技能的开展和各种百G网络的普及,RocketMQ 存储层的瓶颈逐渐闪现,一方面是数据量的膨胀远快于单体硬件,另一方面存储介质速度和单位容量价格始终存在矛盾。在云原生和 Serverless 的技能趋势下,只要经过技能架构的演进才干彻底处理单机磁盘存储空间上限的问题,一起带来更灵活的弹性与本钱的下降,做到 “鱼与熊掌兼得”。

在规划分级存储时,期望能在以下方面做出一些技能优势:

  • 实时: RocketMQ 在音讯场景下往往是一写多读的,热数据会被缓存在内存中,假如能做到 “准实时” 而非选用依据时刻或容量的淘汰算法将数据转储,能够减小数据复制的开支,利于缩短毛病康复的 RTO。读取时发生冷读恳求被重定向,数据取回不需求“冻结时刻”,且流量会被严格约束以防止对热数据写入的影响。
  • 弹性: shared-nothing 架构虽然简略,缩容或替换节点的场景下待下线节点的数据无法被其他节点读取,节点需求坚持相当长时刻只读时刻,待顾客消费完悉数数据,或许执行杂乱的搬迁流程才干缩容,这种 “扩容很快,缩容很慢” 的形态一点都不云原生,更长久的音讯保存才能也会放大这个问题。分级存储规划假如能经过 shared-disk (同享存储) 的方法让在线节点完结署理读取下线节点的数据,既能节省本钱也能简化运维。
  • 差异化: 廉价介质随机读写才能较差,类 LSM 的结构都需求许多的 compation 来紧缩收回空间。在满意针对不同 topic 设置不同的生命周期(音讯保留时刻,TTL)等业务需求的前提下,结合音讯体系数据不可变和有序的特点,RocketMQ 自身需求尽量少的做格局 “规整” 来防止反复兼并的写放大,节省核算资源。
  • 竞赛力: 分级存储还应考虑归档紧缩,数据导出,列式存储和交互式查询分析才能等高阶技能演进。

技能架构选型

1. 不同视角

不妨让咱们站在一个新的视角看问题,音讯体系对用户露出的是收发音讯,位点管理等一系列的 API,为用户供给了一种能够优雅处理动态数据流的方法,从这个角度说:音讯体系拓宽了存储体系的鸿沟。 其实服务端运用大多数是更底层 SQL,POSIX API 的封装,而封装的意图在于简化杂乱度的一起,又完结了信息隐藏。 音讯体系自身重视的是高可用,高吞吐和低本钱,想尽量少的关怀存储介质的挑选和存储自身的体系升级,分片战略,搬迁备份,进一步冷热分层紧缩等问题,削减存储层的长期保护本钱。 一个高效的、完结良好的存储层应该对不同存储后端有广泛的支撑才能,音讯体系的存储后端可所以本地磁盘,可所以各类数据库,也可所以分布式文件体系,目标存储,他们是能够轻松扩展的。

2. 存储后端调研

走运的是,几乎一切的“分布式文件体系”或许“目标存储”都供给了“目标一旦上传或复制成功,即可当即读取”的强共同语义,就像 CAP 理论中的描绘 “Every read receives the most recent write or an error” 保证了“分布式存储体系之内多副本之间的共同性”。关于运用来说,没有 “拜占庭错误” 是十分夸姣的(本来有的数据变没了,破坏了存储节点的数据耐久性),更容易做到“运用和分布式存储体系之间是共同的”,并明显削减运用的开发和保护本钱。 常见的分布式文件体系有 Ali Pangu,HDFS,GlusterFS,Ceph,Lustre 等。目标存储有 Amazon S3,Aliyun OSS,Azure Blob Storage,Google Cloud Storage,OpenStack Swift 等。他们的简略对比如下:

  • API 支撑: 选用目标存储作为后端,一般无法像 HDFS 一样供给充沛的 POSIX 才能支撑,关于非 KV 型的操作往往存在必定功能问题,例如列出许多目标时需求数十秒,而在分布式文件体系中这类操作只需求毫秒甚至微秒。假如选用目标存储作为后端,弱化的 API 语义要求音讯体系自身能够有序管理好这些目标的元数据。
  • 容量与水平扩展: 关于云产品或许大规模企业的存储底座来说,以 HDFS 为例,当集群节点超越数百台,文件到达数亿量级以上时,NameNode 会发生功能瓶颈。一旦底层存储因为容量可用区等要素出现多套存储集群,这种 “本质杂乱度” 在必定程度上削弱了 shared-disk 的架构简略性,并将这种杂乱度向上传递给运用,影响音讯产品自身的多租,搬迁,容灾规划。典型的状况就是大型企业为了削减爆炸半径,往往会部署多套 K8s 并定制上层的 Cluster Federation(联邦)。
  • 本钱: 以国内云厂商官网揭露的典型目录价为例:
    • 本地磁盘,无副本 0.06-0.08 元/GB/月
    • 云盘,SSD 1元/GB/月,高效云盘 0.35 元/GB/月
    • 目标存储单 AZ 版 0.12 元/GB/月,多 AZ 版本 0.15 元/GB/月,低频 0.08 元/GB/月
    • 分布式文件体系,如盘古 HDFS 接口,支撑进一步转冷和 EC。
  • 生态链: 目标存储和类 HDFS 都有足够多的经过出产验证的东西,监控报警层面目标存储的支撑更产品化。

3. 直写仍是转写

计划里,备受瞩意图点在于挑选直写仍是转写,我以为他们不抵触,两个计划 “能够分开有,都能够做强”。

多年来 RocketMQ 运行在依据本地存储的体系中,本地磁盘一般 IOPS 较高,本钱较低但可靠性较差,大规模的出产实践中遇到的问题包含但不限于笔直扩容较难,坏盘,宿主机毛病等。

直写: 指运用高可用的存储替换本地块存储,例如运用云盘多点挂载(分布式块存储形态,通明 rdma)或许直写分布式文件体系(下文简称 DFS)作为存储后端,此刻主备节点能够同享存储,broker 的高可用中的数据流同步简化为只同步位点,在很大程度上减化了 RocketMQ 高可用的完结。

转写: 关于大部分数据密集型运用,出于毛病康复的考虑必须实时写日志,意味着无法对数据很好的进行攒批紧缩,假如仅运用廉价介质,会带来更高的推迟以及更多的内存运用,无法满意出产需求。一个典型思路就是热数据运用容量小的高速介质先次序写,compation 后转储到更廉价的存储体系中。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

直写的意图是池化存储,转写的意图是下降数据的长期保存本钱, 所以我以为一个抱负的终态可所以两者的结合。RocketMQ 自己来做数据转冷,那有同学就会提出反问了,假如让 DFS 自身支撑通明转冷,岂不是更好?

我的了解是 RocketMQ 期望在转冷这个动作时,能够做一些音讯体系内部的格局改动来加快冷数据的读取,削减 IO 次数,配置不同 TTL 等。

相关于通用算法,音讯体系自身对怎么更好的紧缩数据和加快读取的细节愈加了解。 并且自动转冷的计划在审计和入湖的一些场景下,也能够被用于服务端批量转储数据到不同的平台,到 NoSQL 体系,到 ES,Click House,到目标存储,这一切是如此的天然~

4. 技能架构演进

那么分级存储是一个尽善尽美的最终处理计划吗? 抱负很夸姣,让咱们来看一组典型出产场景的数据。

RocketMQ 在运用块存储时,存储节点存储本钱大约会占到 30%-50%。开启分级存储时,因为数据转储会发生必定的核算开支,首要包含数据复制,数据编解码,crc 校验等,不同场景下核算本钱会上升 10%-40%,经过换算,咱们发现存储节点的总体具有本钱节省了 30% 左右。

考虑到商业和开源技能架构的共同性,挑选了先完结转写形式,热数据的存储本钱中跟着存储空间明显减小,这能够更直接的下降存储本钱,在咱们充沛建造好当时的转写逻辑时再将热数据的 WAL 机制和索引构建移植过来,完结依据分布式体系的直写技能,这种分阶段迭代会愈加简明高效,这个阶段咱们愈加重视通用性和可用性。

  • 可移植性: 直写分布式体系一般需求依靠特定 sdk,配合 rdma 等技能来下降推迟,对运用不完全通明,运维,人力,技能杂乱度都有必定上升。保留成熟的本地存储,只需求完结存储插件就能够轻松的切换多种存储后端,不针对 IaaS 做深度绑定在可移植性上会有必定优势。
  • 推迟与功能: 直写形式下存储紧密结合,运用层 ha 的简化也能下降推迟(写多数派成功才被顾客可见),但不管写云盘或许本地磁盘(同区域)推迟都会小于跨可用区的推迟,存储推迟在热数据收发链路不是瓶颈。
  • 可用性: 存储后端往往都有杂乱的容错和毛病转移战略,直写与转写形式在公有云下可用性都满意诉求。考虑到转写形式下体系是弱依靠二级存储的,更适合开源与非公共云场景。

咱们为什么不进一步紧缩块存储的磁盘容量,做到几乎极致的本钱呢?

事实上,在分级存储的场景下,一味的追求过小的本地磁盘容量价值不大。 首要有以下原因:

  • 毛病冗余,音讯行列作为基础设施中重要的一环,稳定性高于一切。目标存储自身可用性较高,假如遇到网络波动等问题时,运用目标存储作为主存储,十分容易发生反压导致热数据无法写入, 而热数据属于在线出产业务,这关于可用性的影响是丧命的。
  • 过小的本地磁盘,在价格上没有明显的优势。 众所周知,云核算是重视普惠和公平的, 假如选用 50G 左右的块存储,又需求等价 150G 的 ESSD 等级的块存储能供给的 IOPS,则其单位本钱几乎是一般块存储的数倍。
  • 本地磁盘容量充足的状况下,上传时能够更好的经过 “攒批” 削减目标存储的恳求费用。读取时能够对“温热” 数据供给更低的推迟和节省读取本钱。
  • 仅运用目标存储,难以对齐 RocketMQ 当时已经存在的丰富特性, 例如用于问题排查的随机音讯索引,守时音讯特性等,假如为了节省少量本钱,极大的削弱基础设施的才能,反向要求业务方自建杂乱的中间件体系是得不偿失的。

分级存储的数据模型与完结

1. 模型与笼统

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

RocketMQ 本地存储数据模型如下:

  • MappedFile:单个实在文件的句柄,也能够了解为 handle 或许说 fd,经过 mmap 完结内存映射文件。是一个 AppendOnly 的定长字节流语义的 Stream,支撑字节粒度的追加写、随机读。每个 MappedFile 具有自己的类型,写位点,创立更新时刻等元数据。
  • MappedFileQueue:能够看做是零个或多个定长 MappedFile 组成的链表,供给了流的无鸿沟语义。Queue 中最多只要最后一个文件可所以 Unseal 的状态(可写)。前面的文件都必须都是 Sealed 状态(只读),Seal 操作完结后 MappedFile 是 immutable(不可变)的。
  • CommitLog:MappedFileQueue 的封装,每个 “格子” 存储一条序列化的音讯到无界的流中。
  • ConsumeQueue:次序索引,指向 CommitLog 中音讯在 FileQueue 中的偏移量(offset)。

RocketMQ 分级存储供给的数据模型和本地模型相似,改动了 CommitLog 和 ConsumeQueue 的概念:

  • TieredFileSegment:和 MappedFile 相似,描绘一个分级存储体系中文件的句柄。
  • TieredFlatFile:和 MappedFileQueue 相似。
  • TieredCommitLog 和本地 CommitLog 混合写不同,依照单个 Topic 单个行列的粒度拆分多条 CommitLog。
  • TieredConsumeQueue 指向 TieredCommitLog 偏移量的一个索引,是严格接连递增的。实践索引的方位会从指向的 CommitLog 的方位改为 TieredCommitLog 的偏移量。
  • CompositeFlatFile:组合 TieredCommitLog 和 TieredConsumeQueue 目标,并供给概念的封装。

2. 音讯上传流程

RocketMQ 的存储完结了一个 Pipeline,相似于拦截器链,Netty 的 handler 链,读写恳求会经过这个 Pipeline 的多个处理器。

Dispatcher 的概念是指为写入的数据构建索引,在分级存储模块初始化时,会创立 TieredDispatcher 注册为 CommitLog 的 dispatcher 链的一个处理器。每逢有音讯发送到 Broker 会调用 TieredDispatcher 进行音讯分发。下面咱们来追踪单条音讯进入存储层的流程:

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

  1. 音讯被次序追加到本地 commitlog 并更新本地 max offset(图中黄色部分),为了防止宕机时多副本发生“读摇摆”,多副本中多数派的最小位点会作为“低水位”被承认,这个位点被称为 commit offset(图中 2500)。换句话说,commit offset 与 max offset 之间的数据是正在等候多副本同步的。

  2. 当 commit offset >= message offset 之后,音讯会被上传到二级存储的 commitlog 的缓存中(绿色部分)并更新这个行列的 max offset。

  3. 音讯的索引会被追加到这个行列的 consume queue 中并更新 consume queue 的 max offset。

  4. 一旦 commitlog 中缓存巨细超越阈值或许等候到达必守时刻,音讯的缓存将被上传至 commitlog,之后才会将索引信息提交,这里有一个隐含的数据依靠,使索引被晚于原始数据更新。这个机制保证了一切 cq 索引中的数据都能在 commitlog 中找到。宕机场景下,分级存储中的 commitlog 或许会重复构建,此刻没有 cq 指向这段数据。因为文件自身仍是被运用 Queue 的模型管理的,使得整段数据在到达 TTL 时能被收回,此刻并不会发生数据流的“泄漏”。

  5. 当索引也上传完结的时分,更新分级存储中的 commit offset(绿色部分被提交)。

  6. 体系重启或许宕机时,会挑选多个 dispatcher 的最小位点向 max offset 从头分发,保证数据不丢失。

在实践执行中,上传部分由三组线程协同作业。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

  1. store dispatch 线程,因为该线程担任本地 cq 的分发,咱们不能长时刻堵塞该线程,否则会影响音讯进入本地存储的“可见性推迟”。因此 store dispatch 每次只会测验对拆分后的文件时刻短加锁,假如加锁成功,将音讯数据放入拆分后的 commitlog 文件的缓冲区则当即退出,该操作不会堵塞。若获取锁失利则当即回来。

  2. store compensate 线程组,担任对本地 cq 进行守时扫描,当写入压力较高时,步骤 1 或许获取锁失利,这个环节会批量的将落后的数据放入 commitlog 中。原始数据被放入后会将 dispatch request 放入 write map。

  3. build cq index 线程。write map 和 read map 是一个双缓冲行列的规划,该线程担任将 read map 中的数据构建 cq 并上传。假如 read map 为空,则交换缓冲区,这个双缓冲行列在多个线程同享拜访时削减了互斥和竞赛操作。

各类存储体系的缓冲攒批战略迥然不同,而线上的 topic 写入流量往往是存在热点的,依据经典的二八原则,RocketMQ 分级存储模块目前采用了 “到达必定数据量”,“到达必守时刻”两者取其小的兼并方法。

这种方法简略可靠,关于大流量的 topic 很容易就能够到达批的最小数据量,关于流量较低的 topic 也不会占用过多的内存。然后削减了目标存储的恳求数,其开支首要包含 restful 协议恳求头,签名和传输等。固然,攒批的逻辑依然存在较大的优化空间,例如 IOT,数据分片同步等各个 topic 流量较为均匀的场景运用相似 “滑动窗口” 的加权均匀算法,或许依据信任值的流量操控战略能够更好的权衡推迟和吞吐。

3. Non-StopWrite 特性

Non-StopWrite 模型实践上是共同性模型的一部分。实践出产中,后端分布式存储体系的断连和网络问题偶然会不可防止,而 Append 模型实践上一种强次序的模型,参阅 HDFS 的 2-3 异步写,咱们提出了一种依据 Append 和 Put 的混合模型。

例如:关于如下图片中的 stream,commit / confirm offset = 150,max offset = 200。此刻写出缓冲区中的数据包含 150-200 的 uncommitted 部分,还有 200 今后源源不断的写入的新数据。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

假定后端存储体系支撑原子性写入,单个上传恳求的数据内容是 150-200 这个区间,当单次上传失利时,咱们需求向服务端查询上一次写入的位点并进行错误处理。

  • 假如回来的长度是 150,说明上传失利,运用需求重传 buffer。
  • 假如回来的长度是 200,说明前一次上传成功但没有收到成功的 response,提高 commit offset 至 200。

而另一种处理计划是,运用 Non-StopWrite 机制马上新切换一个文件,以 150 作为文件名,马上重传 150 至 200 的数据,假如有新的数据也能够马上与这些数据一起上传,咱们发现混合模型存在明显优势:

  • 关于绝大部分没有收到成功的响应时,上传是失利的而不是超时,马上切换文件能够不去 check in 文件长度,削减 rpc 数量。
  • 马上重传不会堵塞后续新的数据上传,不容易因为后端数据无法写出形成反压,导致前端写失利。
  • 不管 150-200 这段数据在第一个文件是到底是写成功仍是失利都无关紧要,因为不会去读取这段数据。尤其是关于不支撑恳求粒度原子写入的模型来说,假如上一次恳求的结果是 180,那么错误处理将会十分杂乱。

补白:社区版本即将支撑该特性。

4. 随机索引重排

21 年的时分,我第一次听到用“读分散”或许“写分散”来描绘一个规划计划, 这两个词简洁的归纳了运用功能规划的本质。各种业务场景下,咱们总是挑选经过读写分散, 挑选经过格局的改动,将数据额外转储到一份功能更好或许更廉价的存储, 或许经过读分散削减数据冗余(削减索引提高了均匀查询代价)。

RocketMQ 会在先内存构建依据 hash 的耐久化索引文件 IndexFile(非 AppendOnly),再经过 mmap 异步的将数据耐久化到磁盘。这个文件是为了支撑用户经过 key,音讯 ID 等信息来追踪一条音讯。

关于单条音讯会先核算 hash(topic#key) % slot_num 挑选 hash slot (黄色部分) 作为随机索引的指针,目标索引自身会附加到 index item 中,hash slot 运用“哈希拉链”的方法处理抵触,这样便形成了一条当时 slot 依照时刻存入的倒序的链表。不难发现,查询时需求多次随机读取链表节点。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

因为冷存储的 IOPS 代价是十分昂贵的,在规划上咱们期望能够面向查询进行优化。新的文件结构相似于保护没有 GC 和只要一次 compation 的 LSM 树,数据结构的调整如下:

1.等候本地一个 IndexFile 完全写满,规避修正操作,在高 IOPS 的存储介质上异步 compation,完结后删除本来的文件。

2.从冷存储查询推迟高,而单次回来的数据量巨细(不太大的场景)并不会明显改动推迟。compation 时优化数据结构,做到用一次查询接连的一段数据替换多次随机点查。

3.hash slot 的指向的 List 是接连的,查询时能够依据 hash slot 中的 item offset 和 item size 一次取出一切 hashcode 相同的记载并在内存中过滤。音讯读取流程

5.音讯读取流程

5.1读取战略

读取是写入的逆进程,优先从哪里取回想要的数据必定存在许多的工程考虑与权衡。如图所示,近期的数据被缓存在内存中,稍久远的数据存在与内存和二级存储上,更久远的数据仅存在于二级存储。当被拜访的数据存在于内存中,因为内存的速度快速存储介质,直接将这部分数据经过网络写会给客户端即可。假如被拜访的数据如图中 request 的指向,存在于本地磁盘又存在于二级存储,此刻应该依据一二级存储的特性综合权衡恳求落到哪一层。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化
有两种典型的主意:

  1. 数据存储被视为多级缓存,越上层的介质随机读写速度快,恳求优先向上层存储进行查询,当内存中不存在了就查询本地磁盘,假如还不存在才向二级存储查询。

  2. 因为在转冷时自动对数据做了 compation,从二级存储读取的数据是接连的,此刻能够把更宝贵一级存储的 IOPS 留给在线业务。

RocketMQ 的分级存储将这个挑选笼统为了读取战略,经过恳求中的逻辑位点(queue offset)判断数据处于哪个区间,再依据详细的战略进行挑选:

  • DISABLE:禁止从多级存储中读取音讯,或许是数据源不支撑。
  • NOT_IN_DISK:不在一级存储的的音讯都会从二级存储中读取。
  • NOT_IN_MEM:不在内存中的音讯即冷数据从多级存储读取。
  • FORCE:强制一切音讯从多级存储中读取,目前仅供测试运用。

5.2预读规划

TieredMessageFetcher 是 RocketMQ 分级存储取回数据的详细完结。

为了加快从二级存储读取的速度和削减整体上对二级存储恳求数,采用了预读缓存的规划:

即 TieredMessageFetcher 读取音讯时会预读更多的音讯数据,预读缓存的规划参阅了 TCP Tahoe 拥塞操控算法,每次预读的音讯量相似拥塞窗口采用加法增、乘法减的流量操控机制。

  • 加法增:从最小窗口开端,每次添加等同于客户端 batchSize 的音讯量。
  • 乘法减:当缓存的音讯超越了缓存过期时刻仍未被悉数拉取,此刻一般是客户端缓存满,音讯数据反压到服务端,在整理缓存的一起会将下次预读音讯量减半。
  • 此外,在客户端消费速度较快时,向二级存储读取的音讯量较大,此刻会运用分段战略并发取回数据。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

6. 守时音讯的分级存储

除了一般音讯,RocketMQ 支撑设置未来几十天的长守时音讯,而这部分数据严重抢占了热数据的存储空间。

RocketMQ 完结了依据本地文件体系的时刻轮,整体规划如左边所示。单节点上一切的守时音讯会先写入 rmq_sys_wheel_timer 的体系 topic,进入时刻轮,出队后这些音讯的 topic 会被还原为实在的业务 topic。

“从磁盘读取数据”和“将音讯索引放入时刻轮”这两个动作涉及到 IO 与核算,为了削减这两个阶段的锁竞赛引入了 Enqueue 作为中转的等候行列,EnqueuGet 和 EnqueuePut 别离担任写入和读取数据,这个规划简略可靠。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

不难发现,一切的音讯都会进入时刻轮,这也是抢占存储空间的根本原因。

  • 写入时,RocketMQ 的分级存储守时音讯针对 EnqueuePut 做了一个分流,关于大于当时时刻数小时的音讯会被写入到依据分级存储的 TimerFlatFile 文件中,咱们保护了一个 ConcurrentSkipListMap<Long /* timestamp */, TimerFlatFile> timerFlatFileTable; 每间隔 1 小时,设置一个 TimerFlatFile,关于 T n 至 T n 1 的守时音讯,会先被混合追加到 T n 所对应的文件中。
  • 读取时,当时时刻 1 小时的音讯将被提早出队,这些音讯又会从头进入本地 TimerStore 的体系 topic 中/此刻,因为守时时刻都是将来一小段时刻的,他们不再会进入时刻轮的结构中。

在这个规划上有一些工程性的考虑:

  • timerFlatFileTable 中的 Key 许多,会不会让分级存储上的数据碎片化?分布式文件体系底层一般运用类 LSM 结构,RocketMQ 只关怀 LBA 结构,能够经过优化 Enqueue 的 buffer 让写分级存储时数据到达攒批的作用。
  • 可靠的位点,Enqueue 到“时刻轮”和 timerFlatFileTable 能够共用一个 commit offset。关于单条音讯来说,只要它进入时刻轮或许被上传成功,咱们就以为一条音讯已经耐久化了。因为更新到二级存储自身需求一些攒批缓冲的进程,会推迟 commit offset 的更新,可是这个缓冲时刻是可控的。
  • 咱们发现偶然本地存储转储到二级存储会较慢,运用双缓冲行列完结读写分离(如图片中绿色部分)此刻音讯被放入写缓存,随后转入读缓存行列,最后进入上传流程。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

分级存储企业级竞赛力

1. 冷数据的紧缩与归档

紧缩是一种经典的时刻与空间交换的权衡,其意图在于经过较小的 CPU 开支,完结更少的磁盘占用或网络 I/O 传输。目前,RocketMQ 的热存储在考虑推迟的状况下,仅对单条大于 4K 的音讯进行单条紧缩存储。关于冷存储服务其实能够做两个层面的紧缩与归档处理。

  • 音讯行列业务层面,关于大多数业务 Topic,其 Body 一般存在相似性,可将其紧缩至原巨细的几分之一至几十分之一。
  • 底层存储层面,运用 EC 纠删码,数据被分成若干个数据块,然后再依据必定的算法,生成一些冗余块。当数据丢失时,能够运用其他的数据块和冗余块来康复丢失的数据块,然后保证数据的完好性和可靠性。典型的 EC 算法后存储空间的运用能够下降到 1.375 副本。

业界也有一些依据 FPGA 完结存储紧缩加快的案例,咱们将继续探索这方面的测验。

2. 原生的只读挂载才能完结 Serverless

业界对 Serverless 有不同的了解,过去 RocketMQ 多节点之间不同享存储,导致“扩容快,缩容慢”,例如 A 机器需求下线,则必须等一般音讯消费完,守时音讯悉数出队才干进行运维操作。分级存储规划经过 shared-disk的方法完结跨节点署理读取下线节点的数据,如右图所示:A 的数据此刻能够被 B 节点读取,彻底释放了 A 的核算资源和一级存储资源。

谈谈 RocketMQ 5.0 分级存储背面一些有应战的技能优化

这种缩容的首要流程如下:

  1. RocketMQ 完结了一个简略的推举算法,正常状况下集群内每一个节点都持有对自己数据独占的写锁。

  2. 待下线的节点做优雅下线,保证近期守时音讯,业务音讯,pop retry 音讯都已被完好处理。上传自己的元数据信息到同享的二级存储,并释放自己的写锁。

  3. 集群运用必定的负载均衡算法,新的节点获取写锁,将该 Broker 的数据以只读的形式挂载。

  4. 将本来节点的元数据注册到 NameServer 对客户端露出。

  5. 关于原节点的写恳求,例如位点更新,将在内存中处理并周期性快照到同享存储中。

总结

RocketMQ 的存储在云原生年代的演进中遇到了更多风趣的场景和应战,这是一个需求全链路调优的杂乱工程。出于可移植性和通用性的考虑,咱们还没有十分有用的运用 DPDK SPDK RDMA 这些新颖的技能,但咱们处理了许多工程实践中会遇到的问题并构建了整个分级存储的框架。在后续的开展中,咱们会推出更多的存储后端完结,针对推迟和吞吐量等细节做深度优化。**

参阅文档:

[1]Chang, F., Dean, J., Ghemawat, S., et al. Bigtable: A distributed storage system for structured data. ACM Transactions on Computer Systems, 2008, 26(2): 4.

[2]Liu, Y., Zhang, K., & Spear, M. Dynamic-Sized Nonblocking Hash Tables. In Proceedings of the ACM Symposium on Principles of Distributed Computing, 2014.

[3]Ongaro, D., & Ousterhout, J. In Search of an Understandable Consensus Algorithm. Proceedings of the USENIX Conference on Operating Systems Design and Implementation, 2014, 305-320.

[4]Apache RocketMQ. GitHub,github.com/apache/rock…

[5]Verbitski, A., Gupta, A., Saha, D., et al. Amazon aurora: On avoiding distributed consensus for i/os, commits, and membership changes. In Proceedings of the 2018 International Conference on Management of Data, 2018, 789-796.

[6]Antonopoulos, P., Budovski, A., Diaconu, C., et al. Socrates: The new sql server in the cloud. In Proceedings of the 2019 International Conference on Management of Data, 2019, 1743-1756.

[7]Li, Q. More Than Capacity: Performance-oriented Evolution of Pangu in Alibaba. Fast 2023

*www.usenix.org/conference/…]Lu, S. Perseus: A Fail-Slow Detection Framework for Cloud Storage Systems. Fast 2023