AutoMQ 与 Apache Kafka 100% 完全兼容,如果你需要一个更低成本、更强弹性和更好性能的 Kafka 服务,你可以毫不犹豫的选择 AutoMQ。
Background
What is AutoMQ
AutoMQ[1] 的诞生受到 Snowflake 的启发,是一款贯彻云优先理念来设计的 Kafka 替代产品。AutoMQ 创新地对 Apache Kafka 的存储层进行了基于云的重新设计,在 100% 兼容 Kafka 的基础上通过将持久性分离至 EBS 和 S3 带来了 10x 的成本降低以及 100x 的弹性能力提升,并且相比 Apache Kafka 拥有更佳的性能。
What is Apache Kafka
Apache Kafka [2]是一款流行的开源的事件流平台,能够每天处理万亿级别的事件。Apache Kafka 诞生于十几年前,引领了流式存储新时代的开启。其通过追加式日志、零拷贝技术等手段极大地提高了数据写入的效率和吞吐。凭借其优秀的扩展性和性能,很快就重塑了企业的数据基础设施架构,在各种规模的企业中均得到了广泛的应用。时至今日,Apache Kafka 仍然拥有非常活跃的社区,并且仍在不断迭代和更新。凭借 Kafka 在流系统领域强大和丰富的生态,Kafka API 当前已经成为流系统领域的事实标准。对 Apache Kafka 是否有足够好的兼容成为很多企业对数据基础设施选型的重要依据。
流系统是重要的数据基础设施,选择适合自己的流系统对于构建一个现代化的数据栈具有重要意义。本篇文章将从多个维度对 AutoMQ 和 Apache Kafka 进行全面对比,以便于读者在选择流系统时可以快速掌握他们的区别,选择适合自己的流系统。
TD;LR
AutoMQ 和 Apache Kafka 的所有区别可用下图表示。如果关心其中对比的细节,则可以继续阅读后续的内容。

弹性 vs 非弹性
云原生与 Serverless 的基石:弹性
经过多年的发展,云原生技术以及公有云已经浸润到各行各业成为现代化数据栈的基础。大家对云原生的概念主要来源于 CNCF 的定义 [3] 以及云厂商的定义 [4] 。无论是哪种定义,都强调了真正的云原生应用需要具备弹性的能力。具备弹性能力的应用可以根据工作负载快速、高效地调整自身实际所消耗的资源;而非原生的应用则需要根据应用的峰值负载进行繁琐的容量评估工作,并且面向峰值工作负载去过量预留资源。下面三幅图 [5] 很好地阐释了云原生应用与非云原生应用在使用资源上的差异。非云原生应用往往采用图 a 中 overprovisioning 的方式来做容量规划。以 Apache Kafka 为例,为了保证服务能够支持峰值吞吐的写入流量以及保证延迟,用户首先需要评估集群机器规格与可以支撑的写入流量的关系,然后得出支撑峰值吞吐所需要的集群规模。在该集群规模基础上再额外预留 30%~50% 的集群容量以避免产生一些预期外的“黑马”流量。这种 overprovisioning 的方式将会产生大量的计算、存储资源浪费。如果采用图 b 的 underprovisioning 方式来做容量规划,则无法支持负载较高的场景导致业务受到影响。真正的云原生需要做到像图 c 中的 scale with elasticiy,即应用程序对资源的消耗是 pay-as-you-go 的。云最大的价值之一就是其近乎无限的资源以及快速的资源供应与销毁。当你不再使用这些云资源时,就一定要及时释放它们;当需要使用时则通过云 API 来快速供应这些资源。只有做到这种弹性,才可以将公有云的优势真正发挥出来。

弹性能力上的比较
结论:AutoMQ >> Apache Kafka

Apache Kafka :Apache Kafka 是一款非常优秀的开源产品。 在他诞生的那个年代,拥有着非常多的技术创新和技术领先性。但是近年来,随着公有云技术、Kubernetes 等技术的普及,对这类数据基础设施的弹性能力提出了新的要求。如果一款产品本身不能拥有非常好的云弹性[5],则其将无法把公有云的能力和 Kubernetes 的能力完全发挥出来。Apache Kafka 诞生于十几年前,本质仍然是软件,而不是服务。很多用户仅仅将 Kafka rehost 到云上,最终发现成本反而变高了,Kafka 本身的运维复杂度也没有降低,背后的关键原因在于 Apache Kafka 存算一体的架构、有状态的 Broker 使得其计算层缺乏弹性,难以进行快速、安全地进行伸缩。缺乏弹性的存算一体架构,不仅仅使得其无法充分利用云的优势,同时也引发了诸如磁盘网络 I/O 争抢、冷读效率等问题。下面总结了一些 Apache Kafka 存在的一些因弹性而产生的问题:
容量评估显著增加 TCO :部署 Apache Kafka 的成本主要来源于其 Broker 机器的计算、存储和网络成本。很多用户都忽视了容量评估带来的复杂性和挑战。为了保证生产系统的稳定,开发人员需要花费大量的时间选取合适的机器规格,并且针对不同机器规格测试性能,才可以准确评估出面向峰值吞吐所需要的集群容量。这里需要考虑副本数、读写比例、网络带宽、SSD IO 带宽、保留时间等各种因素对能承载的写入吞吐的影响,大大增加了投产的成本。并且一旦未来需要扩缩容,则又需要进行重新的容量评估。容量评估是一个重人力介入、高成本的工作,会大大增加用户使用 Apache Kafka 的 TCO。而如果像 AutoMQ 一样支持自动弹性,用户则无需耗费大量的精力根据自己的工作负载去做集群容量规划。当需要
预留容量导致资源浪费 :准确的评估和预测读写的吞吐是一件非常困难的事情。为了避免处理 Apache Kafka 扩缩容时的效率问题,使用者只能按照峰值吞吐提前预留容量。并且为了避免一些没有被准确评估到的黑马流量(这在电商场景中很常见),需要额外预留 30%~50%的容量。试想,如果一个用户平均的写入吞吐为 100MB/s,为了应对峰值吞吐 1GB/s,则需要准备一个可以承载 1.3GB/s~1.5GB/s 的集群,则有 92%的集群容量都是浪费的。
扩缩容影响业务读写,无法应对未来业务变化 :企业的业务是在不断的变化。即使采用提前容量预留的方式,仍然不可避免的在未来需要对集群容量进行调整。在 AutoMQ 服务的客户中,就有来自新能源车企和电商的真实案例。这类企业的特点就是其业务场景往往存在一些营销时刻,例如新车型发布或者电商的折扣促销活动,在该期间 Kafka 集群就需要承载比以往大数倍的流量,此时就需要对 Kafka 集群进行扩容,等到活动结束再将集群缩小至原来的规模。这对企业来说是一个非常高风险并且业务有损的操作。对于 Apache Kafka 而言,扩缩容时期,会涉及 Broker 之间的大量数据复制。这个过程会耗时数小时至数天,更可怕的是,在分区数据迁移期间,这些挪动的分区的读写也会受到影响。每次扩缩容,负责运维 Apache Kafka 的研发人员不仅自己要为容量调整的事情而担惊受怕,同时还需要做好业务方通知与协调,承担迁移期间影响生产消费所带来的潜在业务故障。
面对突发流量无法进行及时干预止血 :如果一开始没有准确的评估好峰值流量,一旦在一些重要的业务时刻产生了一些突发流量,整个 Kafka 集群由于容量不足性能受损。这时,Kafka 集群只能在性能有损的情况下硬抗这些突发流量,眼睁睁看着业务受损,公司遭受损失。
AutoMQ :AutoMQ 对 Apache Kafka 的存储层进行了彻底的云原生改造。基于云优先的理念,将持久性卸载至 EBS、S3 这样成熟的云存储服务。与 Apache Kafka 最大的不同在于整个计算层变成了无状态。由于计算层是无状态的,整个架构也变得极具弹性。在这种弹性架构下,AutoMQ 可以使用云的 Spot 实例、和自动弹性等技术来显著地降低成本,同时也可以在 Kubernetes 上工作得更好。AutoMQ 消除了所有 Kafka 由于缺乏弹性所带来的成本、运维复杂性等问题。下图揭示了 AutoMQ 基于 EBS WAL 和 对象存储(S3)的共享存储弹性架构和 Apache Kafka 存算一体架构的差别。在这种弹性存储架构上,AutoMQ 可以带来诸多好处:
可以使用 Spot 实例来降低成本 : AutoMQ 的弹性存储架构使得 Broker 变成无状态,因此可以使用相比 on-demand 实例有数倍成本优势的竞价实例来降低成本。
可以更好的配合 k8s 工作 : Apache Kafka 也可以部署到 k8s 上,但是没法将 k8s 容器化的优势彻底发挥出来。采用容器技术,相比采用虚拟机,k8s 可以更加快速地创建和销毁 pod。AutoMQ 的弹性架构使得其在 k8s 上可以具有更快地弹性。而 Apache Kafka 由于其 scale in/out 时涉及多副本在各个 Broker 之间的大量数据复制,无法利用 k8s 容器化对弹性带来的益处。
支持自动弹性 : 具备快速、安全地扩缩容能力是自动弹性的基础。AutoMQ 的弹性存储架构进一步催生了秒级分区迁移、流量自动重平衡等关键特性,使得 AutoMQ 可以做到真正的自动弹性。

AutoMQ 对 Kubernetes 具有更好的支持

Kubernetes 是云原生技术领域中的重要创新也是云原生技术的集大成者。Kubernetes 充分利用了云原生的容器技术、弹性、IaC、声明式 API 等云原生手段为企业提供了一个标准化的、通用的、高效的云原生技术底座。企业通过遵循云原生的最佳实践,将符合云原生技术理念的应用迁移部署在 Kubernetes 上,可以从其高效的自动化运维部署、资源管理、丰富的生态中获益。例如 Aliyun Cloud 上的核心服务基本都已经跑在 K8s 之上。使用 Kubernetes 在具有一定规模的企业中将会获得更大的益处。AutoMQ 的很多大型客户很多都在大量使用 K8s 或者正在将企业内的核心数据基础设施往 K8s 上迁移。
AutoMQ 对 k8s 有着绝佳的支持。Apache Kafka 社区在 K8s 生态中,也有像 Bitnami 和 Strimzi 这样优秀的产品。在他们的社区中也有开发者呼吁支持 AutoScaling 的声音 [10] [11],但是由于 Apache Kafka 本身存算一体的架构导致其在 k8s 上难以进行横向的伸缩。将 Apache Kafka 部署到 k8s 上本质上只是将原本在 IDC 机房部署的 Kafka rehost 到 k8s 上而已,难以将 K8s 的优势真正发挥出来。至于相反的是,AutoMQ 通过对 Kafka 存储层的云原生改造,支持了无状态的 Kafka Broker。你可以将 AutoMQ 部署到 AWS EKS 之上[12]并结合使用 Karpenter [13]、Cluster AutoScaler [14]等 k8s 生态产品支持 AutoMQ 的自动弹性。
成本对比
在 AutoMQ 官方文档 Cost-Effective: AutoMQ vs. Apache Kafka[6] 中,比较了 AutoMQ 和 Apache Kafka 在 AWS 上运行时的真实云账单差异。总体而言,在满足相同的性能指标下,在一个比较典型的场景下,AutoMQ 可以相比 Apache Kafka 可以节约 90%的成本 。下图详细揭示了在 AWS 云上自建 Apache Kafka 和使用 AutoMQ 时,这些成本差异主要来自于哪里。

计算层 :
Spot 实例 :例如 aws cn-northwest-1 的 r6i.large 的 on-demand 价格为 ¥0.88313/hour,Spot 实例的价格为 ¥0.2067/hour。在我们举例的这个 case 中,使用 spot 实例可以相比 on-demand 实例节约 76%的成本。
AutoScaling :AutoMQ 由于其计算层是无状态的,因此有实现 AutoScaling 的基础。对于 Apache Kafka 来说,由于其本身缺乏弹性,扩缩容操作对于其来说是一个极其高风险和耗时的操作,普通的扩缩容操作都基本难以实施,更不要提实现 AutoScaling 这样的能力了。AutoMQ 可以通过快速地 AutoScaling 为用户提供与实际变化的负载相匹配的资源从而来减少资源浪费,降低成本。用户流量的波动越大,则通过 AutoScaling 节约的费用则越多。在 Cost-Effective: AutoMQ vs. Apache Kafka[6] 中,我们模拟了一个和真实场景比较贴近的周期性负载的场景。使用 AutoMQ 的自动弹性能力,对计算实例进行自动伸缩,在这种波动性的负载中,平均每天可以节约 90% 左右的实例费用。
相比 Apache Kafka,AutoMQ 可以用更少的机器和更小的规格承载更大的读写吞吐 :AWS 云上的机器,其网络带宽与其规格相关。只有规格更大的机型,才可以享用更大的网络带宽。假设是 1:1 的写入模型,针对 1 份写入流量,AutoMQ 的出流量会包含消费者消费的 1 份流量以及写入 S3 的 1 份流量。同样情况下采用 Apache Kafka,采用 3 副本会包含消费者消费的 1 份流量以及额外的 2 份分区复制的流量。综上分析,针对一个 Broker,AutoMQ 只需选择可以承载 2 份出流量网络带宽的 EC2 既可满足诉求,而 Apache Kafka 需要承载 3 份出流量的网络带宽的 EC2 才可以满足诉求,这使得 AutoMQ 可以使用比 Apache 规格小得多的机型既可承载相同的读写吞吐。
无需容量评估,减少人力成本 :AutoMQ 企业版提供基于吞吐的计费。用户无需关心集群可以承载的流量与实际底层计算、存储、网络上的关系。AutoMQ 的技术专家们耗费了大量时间帮助用户选择最优机型和最佳配置。无论是新建集群还是扩缩容,用户无需自己耗费大量时间和人力再次评估底层资源消耗与实际可承载的吞吐之间的关系。如果启用自动弹性,则可以完全像使用 Serverless 服务一样使用 AutoMQ。
存储层 :
Apache Kafka 依赖昂贵的本地存储 :为了保证 Kafka 的延迟满足要求,用户需要使用 SSD 来存储 Kafka 的数据。为了应对一些有回溯消费需求的场景,用户需要将这些数据在 Kafka 集群上保留一段时间。由于 Kafka 是一个数据密集型的数据基础设施,其中涉及到大量的数据写入和存储。以 us-east-1,GP3 的 EBS 单价为 0.08 USD/GB 每月。假设每天的平均写入流量是 100MB/s,数据保留时间为 24h,则每个月在存储成本上将要消耗 691.20 USD。而使用 AutoMQ 的存储成本则仅为 188.42 USD 每月。可以节省 73%的存储成本 。如果用户具有更大的吞吐和保留时间,在存储费用的绝对值上将会有更加明显的体感。对于一些大规模的企业,仅在存储成本上 AutoMQ 即可相比 Kafka 每月节约数十万美元。
无需容量评估,减少人力成本 :如果使用 Apache Kafka 需要为每个 Broker 配置多少本地磁盘需要自行测试、验证和评估。与计算层相同,AutoMQ 则无需用户自行进行集群容量评估。
网络 :
- 集群内部的跨 AZ 费用 :Apache Kafka 为了保证数据的持久性,需要设置 3 副本。Kafka 通过 ISR 来保证数据的持久性。海外云供应商像 AWS 和 GCP 都会针对跨可用区的网络流量进行收费。不仅仅是 Apache Kafka,像 Confluent、Redpanda 等这类基于多副本复制来保证数据持久性的模型,都将在 AWS 这类对跨可用区收费的云上付出巨大的网络成本[8]。而 AutoMQ 在集群内部不涉及任何数据复制。AutoMQ 将数据的持久性卸载至 EBS 、S3 这类本身内部具有多副本机制的云存储服务,在 AutoMQ 集群层面,只需要单个数据副本即可保证数据持久性。

性能对比
与 WarpStream[9]这种以牺牲延迟为代价的方案不同,AutoMQ 在流存储引擎上的创新不仅没有牺牲 Kafka 在高吞吐、低延迟上的优势,同时在 Catch-up Read 场景由于进行了冷热数据的隔离,反而相比 Kafka 拥有更好的性能。AutoMQ 采用 OpenMessaging Benchmark 对 AutoMQ 和 Apache Kafka 的性能进行了全面的对比。具体的 Benchmark 细节可以参考 Benchmark: AutoMQ vs. Apache Kafka[7],本文针对其中几个关键几个进行说明。
固定规模下延迟和吞吐性能对比
固定规模下 AutoMQ 相比 Apache Kafka 的主要优势是:
相同机器规模下,极限吞吐是 Apache Kafka 的 2X : AutoMQ 基于 EBS 底层的多副本来保障数据高可靠,上层无多余的复制,而 Apache Kafka 需要通过 ISR 三副本来保障数据高可靠。在不考虑 CPU 和网络瓶颈下,AutoMQ 和 Apache Kafka 都跑满硬盘带宽,AutoMQ 的理论吞吐上限是 Apache Kafka 的 3 倍。
相同集群规模和流量(500 MiB/s)下,AutoMQ 的发送延迟 P999 是 Apache Kafka 的 1 / 4,即使在 AutoMQ 在两倍(500 MiB/s : 1024 MiB/s)的流量下,发送延迟 P999 仍是 Apache Kafka 的 1 / 2 :
AutoMQ 使用 Direct IO 绕过文件系统直接写 EBS 裸设备,无文件系统开销,可以获得比较稳定的发送延迟。
Apache Kafka 通过 Buffered IO 将数据写到 page cache ,写到 page cache 后就返回成功,由操作系统在后台将脏页刷到硬盘。文件系统开销、消费冷读和 page cache 缺页的不确定性均可能导致发送延迟的抖动。


冷读时的性能对比
冷读(Catch-up reads)指的是消费 offset 在当前时刻之前的数据。当消费者由于自身原因消费速率赶不上生产速率或者需要回溯消费时都会涉及到冷读。冷读是 Kafka 消费中常见和重要的场景,对于评估 Kafka 的性能具有重要的参考意义。冷读的常见场景包括:
消费速率跟不上生产者 : 对于消息来说,消息通常用作业务间的解耦和削峰填谷。削峰填谷要求消息队列能将上游发送的数据堆积住,让下游慢慢的消费,这时候下游追赶读的数据都是不在内存中的冷数据。
周期性批处理任务的回溯消费 :对于流来说,周期性的批处理任务需要从几个小时甚至一天前的数据开始扫描计算。
故障恢复场景 :消费者宕机故障若干小时后恢复重新上线;消费者逻辑问题,修复后,回溯消费历史数据。
结果总结

AutoMQ 冷读时不会影响写入流量 :相同集群规模下,在追赶读时,AutoMQ 的发送流量没有受到任何影响,而 Apache Kafka 的发送流量下降了 80%:这是由于,Apache Kafka 在追赶读时会读取硬盘,且没有做 IO 隔离,这占用了 AWS EBS 的读写带宽,导致写硬盘带宽减少,发送流量下降;作为对比,AutoMQ 读写分离,在追赶读时不会读硬盘,而是读对象存储,不会占用硬盘读写带宽,也就不会影响发送流量。
AutoMQ 冷读时不会有延迟性能的劣化 :相同集群规模下,在追赶读时,相较于仅发送,AutoMQ 的平均发送延迟上升了约 0.4 ms,而 Apache Kafka 则飙升了约 800 ms。Apache Kafka 发送延迟升高有两方面原因:其一是前文提到的,追赶读会占用 AWS EBS 读写带宽,这会导致写入流量下降、延迟升高;其二是追赶读时,读硬盘中的冷数据会污染 page cache,同样会导致写入延迟升高。
AutoMQ 与 Apache Kafka 的关系
简而言之,AutoMQ 是 Apache Kafka 社区分叉项目。在保留 Apache Kafka 计算层所有代码的基础上,AutoMQ 找到了一个合适的切点(LogSegment)对 Kafka 的存储层进行了彻底的替换,重新设计和实现了基于 EBS WAL 和 S3 的新共享存储流引擎 S3Stream[16]。因此做到了对 Apache Kafka 的 100%兼容。AutoMQ 是 Apache Kafka 生态的忠实拥护者。并且会不断跟进 Apache Kafka 社区的最新修复与改动,始终保持和 Kafka 上游社区的完全兼容。因此,如果你本来就已经在使用 AutoMQ,则无需对上层的应用和已经围绕 Apache Kafka 建设的数据基础设施做任何改造即可无缝迁移至 AutoMQ。

参考资料
[1] AutoMQ: https://github.com/AutoMQ/automq
[2] Apache Kafka: https://kafka.apache.org/
[3] CNCF Cloud-Native: https://github.com/cncf/toc/blob/main/DEFINITION.md
[4] AWS What is Cloud-Native: https://aws.amazon.com/what-is/cloud-native/
[5] What Is Cloud Elasticity?: https://www.cloudzero.com/blog/cloud-elasticity/
[6]Cost-Effective: AutoMQ vs. Apache Kafka: https://docs.automq.com/automq/benchmarks/cost-effective-automq-vs-apache-kafka
[7] Benchmark: AutoMQ vs. Apache Kafka: https://docs.automq.com/automq/benchmarks/benchmark-automq-vs-apache-kafka
[8] Introducing Confluent Cloud Freight Clusters: https://www.confluent.io/blog/introducing-confluent-cloud-freight-clusters/
[9] WarpStream: https://www.warpstream.com/
[10] [bitnami/kafka ] Auto Scaling: https://github.com/bitnami/charts/issues/22733
[11] How to scaling up Kafka Broker: https://github.com/strimzi/strimzi-kafka-operator/issues/1781
[12]使用 AutoMQ 实现 Kafka 大规模成本及效率优化: https://aws.amazon.com/cn/blogs/china/using-automq-to-optimize-kafka-costs-and-efficiency-at-scale/
[13] Karpenter:https://karpenter.sh/
[14] autoscaler: https://github.com/kubernetes/autoscaler
[15] How does AutoMQ achieve 100% protocol compatibility with Apache Kafka? https://www.automq.com/blog/how-automq-makes-apache-kafka-100-protocol-compatible
[16] S3Stream Overview: https://docs.automq.com/automq/architecture/s3stream-shared-streaming-storage/overview