01

TL;DR

是的,你没有看错。AutoMQ[1] 当前已经支持完全构建于像 S3 这样的对象存储之上。你可以参考快速上手[3] 即刻开始体验。AutoMQ 在已有的流存储引擎之上仅仅通过对顶层 WAL 的抽象进行拓展实现少量代码即可做到一些友商引以为傲的的特性,即将流系统完全构建于像 S3 对象存储之上。值得一提的是,我们也已经将这部分源码完全公开,开发者可以利用 S3Stream[2] 流存储引擎轻松在自己的环境中拥有一个完全部署在对象存储之上的 Kafka 服务,具备极低的存储成本和运维复杂度。AutoMQ 核心的流存储引擎可以如此轻松的完成这项能力和其围绕 WAL 与 共享存储架构设计的优秀流存储顶层抽象是分不开的。也正是基于这套优秀的顶层抽象我们实现了极具创新的 S3Stream[2] 流存储引擎。在这篇文章中,我们将与你分享 AutoMQ 共享流存储引擎的设计细节、背后的思考以及演进的过程。看完前面的内容,你也会真正明白为什么我们说只需要百行代码即可实现将 Kafka 运行在 S3 之上。

02

从共享存储架构启航

在十几年前,Kafka 诞生于一个以 IDC(Internet Data Center)为主要场景的时代。当时的计算和存储资源通常是紧密耦合在一起的,形成了一种存算一体化的 Share-Nothing 架构。这种架构在当时的物理数据中心环境中非常有效,但随着公有云技术的成熟,这种架构的局限性也逐渐显现出来。存算一体的 Share-Nothing 架构由于计算存储强耦合,没有办法将存储层彻底解耦出来将持久性、高可用等能力卸载给云存储服务。这也意味着 Share-Nothing 架构无法发挥成熟的云存储服务规模化的技术和成本红利。此外,存算一体的架构也使得 Kafka 缺乏弹性、难以扩展。Kafka集群进行容量调整时,将涉及大量的数据复制。这会影响其容量调整的效率,并且在容量调整期间还将影响正常的读写请求。AutoMQ 致力于充分发挥云的优势,贯彻 Cloud-First 的理念,通过共享存储架构,AutoMQ 将数据的持久性解耦出来卸载给了像 S3、EBS 这样成熟的云存储服务,可以充分挖掘了这些云存储服务的潜力。Kafka 因为 Share-Nothing 架构带来的缺乏弹性、成本高昂、运维复杂等问题在 AutoMQ 全新的共享存储架构实现下都不再成为一个问题。

百行代码实现 Kafka 运行在 S3 之上_共享存储

03

集成流存储顶层抽象:Shared WAL + Shared Object云的步骤

AutoMQ 共享存储的核心架构是  Shared WAL 和 Shared Object。在这套共享存储架构抽象下我们可以有各种不同的实现。通过 Shared WAL 的抽象我们可以将这种 WAL 实现迁移到任何共享存储介质上,享受不同共享存储介质本身带来的优势。熟悉软件工程的读者一定知道,任何软件设计都有 trade-off,不同的共享存储介质随着他们的 trade-off 变化也会带来不同的优点和缺点。而 AutoMQ 基于 Shared WAL  的这种顶层抽象让我们以不变应万变。AutoMQ 可以将这种 Shared WAL  的实现自由迁移到任何共享存储服务之上,甚至还可以将他们组合在一起。Shared Object 则主要构建于云上成熟的对象存储服务,可以享有极低的存储成本,享受云对象存储服务规模化的技术成本红利。随着 S3 API 成为对象存储协议的事实标准,AutoMQ 也可以通过 Shared Object 去适配各种不同的对象存储服务,为用户提供多云存储的方案。Shared WAL 则可以适配像 EBS 、S3E1Z 这样的各种低延迟的存储介质,为用户提供低延迟的流服务。

百行代码实现 Kafka 运行在 S3 之上_存储引擎_02

百行代码实现 Kafka 运行在 S3 之上_存储引擎_03

云上最佳 Shared WAL  实现:EBS WAL

WAL 最早是应用在关系数据库中,为了实现数据原子性和一致性。随着像 S3、EBS 这样的云存储服务的成熟,将 WAL 结合低延迟存储再将数据异步写入到 S3 这样的低成本存储中则可以兼顾延迟和成本。而 AutoMQ 则是在流领域首个基于共享存储架构来这样使用 WAL 的玩家,将不同云存储的优势都一起彻底的发挥了出来。我们也认为,EBS WAL 这种实现是云上流存储引擎的最佳实现,因为其将 EBS 低延迟、高持久的优点和对象存储低成本的优点全部结合在了一起。并且通过巧妙的设计,规避了 EBS 昂贵的缺点。下图是 EBS WAL 的核心实现流程:

  1. Producer 通过 S3Stream 流存储引擎将数据写入 EBS WAL。落盘成功后立即返回客户端成功。充分利用了 EBS 低延迟、高持久的特征。
  2. 对于刚写入的数据消费者可以直接从缓存中读取
  3. 缓存中的数据在异步批量、并行地写入 S3 以后则会失效
  4. 消费者如果需要读取历史数据则直接从对象存储上进行读取

百行代码实现 Kafka 运行在 S3 之上_对象存储_04

一种常见的误解在于将这种构建于 EBS 上的 Shared WAL 与 Kafka 的分层存储弄混。其实主要区别他们的方式很简单,即判断计算节点 Broker 是否为彻底的无状态。对于 Confluent、Aiven 实现的分层存储来说,他们的 Broker 仍然是有状态的。Kafka 的分层存储要求其分区的最后一个日志段必须在本地磁盘上,因此他们在本地存储上的数据是强耦合计算层的 Broker 的,而 AutoMQ 实现的 EBS WAL 则没有这种限制。当 Broker 节点崩溃后,其他健康的 Broker 节点可以通过 Multi Attach 的方式在毫秒时间内接管 EBS 卷,将其上固定大小(通常是 500MB)的少量 WAL 数据写入到 S3 然后删除卷既可。

百行代码实现 Kafka 运行在 S3 之上_存储引擎_05

云上最佳 Shared WAL  实现:EBS WAL

S3 WAL 是 Shared WAL 共享存储架构自然演进的结果。AutoMQ 当前支持将存储层完全构建于 S3 之上,则是 Shared WAL  的一种具体实现罢了。直接构建于 S3 的这种 WAL 实现我们称之为 S3 WAL。得益于 Shared WAL 的顶层抽象和 EBS WAL 的实现基础,S3 WAL 的核心流程与 EBS WAL 的实现相同,因此 AutoMQ 团队仅在几周内即可完成了 S3 WAL 实现的支持。实现 S3 WAL 一方面是 AutoMQ Shared WAL 架构自然演进的结果,另外一方面也可以帮助 AutoMQ 拓宽能力边界。当采用 S3 WAL 时,用户的所有数据都将全部写对象存储,因此相比 EBS WAL 则会带来一些延迟的上升。但是伴随着这种 trade-off,整个架构由于依赖的服务将会更少从而变得更加精简高效。而在像 AWS 这样不提供跨 AZ 可用区 EBS 的“特殊”云厂商之上,以及私有 IDC 场景使用 minio 这种自建对象存储服务的场景,S3 WAL 的架构也将为其提供更强的跨 AZ 可用性保证和灵活性。

04

S3WAL Benchmark

AutoMQ 在实现 S3WAL 对其性能上做了很多优化,尤其是其延迟表现。在我们的测试场景中,S3 WAL Append 的平均延迟为 168ms,P99 296ms。

百行代码实现 Kafka 运行在 S3 之上_共享存储_06

Kafka Produce 请求处理延迟平均 170ms,P99 346ms。

百行代码实现 Kafka 运行在 S3 之上_对象存储_07

平均发送延迟 230ms,P99 489ms。

百行代码实现 Kafka 运行在 S3 之上_对象存储_08

05

AutoMQ 是如何通过百行代码实现 S3 WAL 的

在 AutoMQ 的 Github 仓库中,你可以找到核心流存储库 S3Stream[2]。其中的类 com.automq.stream.s3.wal.WriteAheadLog 包含了 WAL 的顶层抽象,实现类 ObjectWALService 则包含了 S3 WAL 的 100 多行实现代码。从这个意义上来说我们确实通过了 100 多行实现类的代码配合已有 EBS WAL 的代码基础设施完成了将 AutoMQ 完全构建于 S3 之上。当然,几百行代码的实现并不意味着你真的只需要写 100 多行代码就能实现 Kafka 在 S3 之上的运行。这只是表象。关键在于我们能够充分理解 AutoMQ 这种基于 WAL 的共享存储架构理念。在这套体系之上,无论未来是实现完全基于 S3 的共享存储,还是在其他共享存储介质上实现,思路都是一致的。在 AutoMQ 的架构中,Shared WAL 是核心组件之一。通过对 Shared WAL 进行顶层抽象组织代码,我们可以将 Shared WAL  的实现方法迁移至其他任何共享存储介质。具体来说,当你在 AutoMQ 上实现一个共享存储 WAL 时,真正的工作量和复杂度已经被底层架构所消化。你只需要关注如何高效地将 WAL 写入和读取到目标存储介质上。正因为 AutoMQ 的流存储引擎已经为你铺好了道路,当你充分理解 Shared WAL 的理念和 S3Stream 流存储引擎时候,实现一个完全基于的 S3 的 S3WAL 这项工作也就像写 100 行代码那么简单了。

06

总结

本文通过介绍 AutoMQ 存储架构背后的思考和演进为大家揭示了其最核心的基于 Shared WAL  的共享存储架构理念。而未来,AutoMQ 也将持续优化基于这套抽象的流存储引擎底座的能力,在其上为大家构建更加强大的 Kafka 流服务。不久的将来,S3E1Z WAL 也将正式和大家见面,请大家对我们保持关注。

参考资料

[1] AutoMQ:  https://github.com/AutoMQ/automq [2] S3Stream: https://github.com/AutoMQ/automq/tree/main/s3stream
[3] Direct S3 Cluster 部署:   https://docs.automq.com/zh/automq/getting-started/deploy-direct-s3-cluster

关于我们

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

🌟 GitHub 地址: https://github.com/AutoMQ/automq

💻 官网: https://www.automq.com\?utm\_source=wechat 
👀 B站:AutoMQ官方账号
🔍 视频号:AutoMQ