Skip to main content

云原生重塑 Kafka 架构

本文中提及的 AutoMQ Kafka 术语,均特指安托盟丘(杭州)科技有限公司通过 GitHub AutoMQ 组织下开源的 automq-for-kafka 项目。

项目创立的契机

随着云成为现代 IT 的基础设施,越来越多的企业将自己的业务和依赖的底层组件迁移到云上或者直接基于云来构建。如果上云只是将产品从自建机房物理机部署转换成云上虚拟机部署,可能难以从云的弹性能力、按量付费和低成本规模化云服务中获益。

Apache Kafka 作为大规模日志传输分布式系统诞生。Apache Kafka 面向数据中心进行架构设计,通过 ISR 多副本机制保障数据可靠性,将数据零拷贝持久化到本地盘获得极高的吞吐。在数据中心中部署应用为主流的年代,Apache Kafka 在机房有充足的带宽和便宜的 HDD 盘,为用户提供了高吞吐和低成本的流传输通道,成为了实时流处理领域事件流传输通道的事实标准。

在云的时代,最理想的工作模式是无需提前按照峰值预留资源,可以随着需求动态弹性 pay-as-you-go。Apache Kafka 的数据和机器绑定,需要数小时甚至1天才能完成扩缩容后的流量重平衡,这使得用户即使将 Apache Kafka 部署到云上,仍旧需要为峰值保留资源。除此之外,主流云厂商的云盘都已经提供了非常高的可靠性,以 AWS EBS IO2 为例,其本身提供了 99.999% 的可靠性,Apache Kafka 的多副本机制并不能增加更多的可靠性,反而浪费了存储和带宽,进一步提高成本。

因此是时候基于云重新设计一个云原生的 Kafka 了!

真正的云原生应用

首先需要定义什么是真正的云原生应用,然后才能设计一个云原生的 Kafka。

我们认为真正的云原生应用具备以下 2 个特征:

云经济:面向云的计费项进行架构

  • 面向资源限制设计: 云上的资源都有限制,云原生应用的架构设计中就需要识别和规避资源短板,资源限制决定了理论上限。以 Apache Kafka 为例,在三副本、发送/消费 1:1 的场景下,AWS EC2 规格为 m6in.large 的实例单机的理论上限为 (基准带宽 390 MB /s) / (1份消费流出 + 2 份复制流出) = 130 MB/s。但是如果基于云盘来存储数据,无需额外的副本,那么 m6in.large 单机的理论上限就变为 (基准带宽 390 MB /s) / (1份消费流出) = 390 MB/s,相同的机器规格,理论吞吐是原来的 3 倍。
  • 充分利用云厂商免费额度: 云上的服务通常对于小规格有免费/优惠额度,云原生应用需要充分利用小规格来大大节约成本,通过小规格的组合来支持大规模的服务。例如 AWS GP3 云盘有 3000 IOPS、125MB/s 的免费额度,10 个免费额度的 GP3 相比一块 3W IOPS 1250MB/s 的 GP3 每月能节省 1300 ¥。
  • 基于对象存储构建存储系统: AWS 的 S3 背后有数百名工程师经过数年的不断优化,目前已经是世界上最便宜的存储之一,并且能保证超高可用性。存储系统选择对象存储作为主存储,不仅可以大幅节省存储成本,还可以将数据卸载到对象存储降低软件的复杂度。
  • 充分利用 Spot 实例: 主流公有云均有提供相比按需实例价格更加低廉的 Spot 实例。Spot 实例的特征是运行一段时间后,公有云会根据其本身的计算实例容量或者 Spot 实例竞价情况回收、中断 Spot 实例。 AutoMQ Kafka 可以充分利用 Spot 实例带来至多90%的云计算实例成本节约。

极致弹性:pay-as-you-go

  • 分钟级扩缩:云上的资源都是按量付费的,计费单元可以精细到秒。云原生应用也应该是按量付费的,当流量上涨的时候可以分钟级扩容,当流量下降的时候也可以及时释放掉不需要的资源。
  • 细粒度弹性:云原生应用需要面向小规格进行设计,小规格意味着弹性的粒度就会更细,最终 Serverless 的成本也会更低。

AutoMQ for Kafka ——真正云原生 Kafka

AutoMQ for Kafka (简称 AutoMQ Kafka ) 一款基于云重新设计的云原生 Kafka。AutoMQ Kafka 100% 兼容 Kafka 协议,充分兑现云的红利,相比 Apache Kafka,AutoMQ Kafka 提供至多 10x 成本节约和至多 800x 效率提升。

架构概览

AutoMQ Kafka 基于 Apache Kafka 进行云原生架构重构:

  • Controller:控制面,持续监测 Broker 的水位,自动发起 Partition 在 Broker 间的流量重平衡。
  • Broker:“无状态” 计算节点,数据全都卸载到共享存储 S3Stream,可以秒级关机下线。
  • S3 Stream:S3 Stream 是基于云盘和对象存储构建的低延迟、高吞吐、低成本、无限存储的流存储库。云盘作为 写入缓冲区 Delta WAL▸ (2GB空间) 提供毫秒级快速响应,对象存储作为主存储提供无限容量低成本存储。

100% 协议兼容

AutoMQ Kafka 基于 Apache Kafka 代码进行最小化改动,从最小存储单元 LogSegment 代码切入,将 LogSegment 中的文件分类映射到对应的 S3Stream,完成 Broker 的数据卸载到共享存储。上层逻辑例如网络、事务和 Compact Topic 等几乎所有代码均被复用,保持一致,做到 100% 的协议和语义兼容。

10x 成本节约

存储

对象存储是云上最便宜的存储之一(AWS S3 存储价格仅为 GP3 的 28%)。对象存储采用按量付费模式,拥有几乎无限的容量,但同时其读写耗时通常在 100ms 之上,并且按照 API 调用次数收费。如果直接用来持久化数据造成用户的写入耗时和 API 调用费用过高。因此我们可以选择一个高性能、低延时的存储作为一个缓冲层,将高频的小数据块转换成低频的大数据块。

在调研基于 SSD 自建多副本、NAS 和云盘作为缓冲层的方案后,最终决策出来基于云盘是最优的方案:

  • 基于 SSD 自建多副本:组建 3副本浪费 2 份 Network Out 流量,使得计算成本上升;
  • NAS:云上 NAS 在相同 IOPS 和吞吐下,成本和写入延时高于云盘;
  • 云盘:成本最低,并且在云上有较高的免费额度;

AutoMQ Kafka 使用云盘作为缓冲层,写入 S3Stream 的数据持久化到云盘的 Delta WAL 后,就可以响应给上层写入成功,由 Delta WAL 提供高性能、低延时的写入。当 Delta WAL 操作 500MB 后,后台会异步触发上传 Stream Set Object 到对象存储,由对象存储提供按量付费、低成本、无限的存储,实现存储层的 pay-as-you-go。

AutoMQ Kafka 通过对象存储作为主存储的模式相比 Apache Kafka(<3.6.0 无分层存储) 云上三副本至多可以节省 10x 成本。

(Apache Kafka 存储成本:GP3 0.08$ GB每月 * 3 副本 / 0.8 磁盘水位) / (AutoMQ Kafka 存储成本:S3 0.023$ GB每月 + S3 调用费用) ~= 10x

计算

Apache Kafka 作为 IO 密集型的应用,网络通常会先成为瓶颈。AutoMQ Kafka 基于云盘将数据写入到 Delta WAL,无需走网络将数据复制到其他机器,由云盘来保障数据的高可靠。云盘的写入和读取是不计算在网络消耗中的,AutoMQ Kafka 后台异步上传到对象存储消耗一份流量。对比 Apache Kafka 三副本两份流量的扇出复制,AutoMQ Kafka 在数据持久化流程只消耗了一半的流量。在发送/消费比为 1:1 的场景下,AutoMQ Kafka 的单机吞吐为 Apache Kafka 的 1 / ((1消费 + 1上传对象存储) / (1消费 + 2复制)) = 1.5x。

AutoMQ Kafka 除了在相同的机器成本能发挥更高的性能优势以外,AutoMQ Kafka 的 Serverless 分钟级弹性扩缩对于有流量峰谷的业务来说也是成本节约的大杀器。

  • 分钟级节点扩缩: AutoMQ Kafka 通过云厂商的 Auto Scaling Group 持续监测 Broker 的平均网络水位,当水位高于/低于阈值时,就会直接触发集群的扩缩容。
  • 秒级流量重平衡调度: AutoMQ Kafka 的控制面会持续监测 Broker 间的流量情况,秒级完成 Partition 负载均衡调度。

通过分钟级节点扩缩和秒级流量重平衡调度, AutoMQ Kafka 可以始终将集群保持在一个能恰好满足业务需求的状态,实现计算层的 pay-as-you-go。

对于流量峰谷很明显的业务来说,AutoMQ Kafka 的 Serverless 形态结合全新的计算架构,综合下来可以完成 10x 的计算成本节约。

100x 效率提升

AutoMQ Kafka 是一个 “无状态” 应用。虽然看似 AutoMQ Kafka Broker 有一个基于云盘的 Delta WAL,但是实则 AutoMQ Kafka Broker 仍旧是“无状态”的。

从 Broker 分钟级缩容下线和 Partition 秒级迁移两个场景来探索一下 AutoMQ Kafka 是如何做到“无状态”:

  • Broker 分钟级缩容: 前面有提到 Delta WAL 里面会缓冲小于 500MB 的数据。当 Broker 接受到 kill -15 优雅关机信号后,Broker 会将缓冲区中的数据上传到对象存储中,然后完成优雅下线。通常云上的机器都有网络 Burst 能力,以 m6in.large 为例,网络 Burst 性能 25 Gbps,不到 2s 就能完成 Delta WAL 上传。
  • Partition 秒级迁移: Partition 秒级迁移其实和 Broker 分钟级扩缩容类似。当 Partition 要转移到其他 Broker,首先会触发当前 Broker 的 Delta WAL 上传,然后在目标 Broker 打开 Partition 的时候就能读到对应的数据了。

结合 Auto Scaling 容量探测,触发集群自动扩缩,AutoMQ Kafka 可以 Serverless 免运维化。

对比 Apache Kafka,借用 Confluent 的示例,在 3 台 Broker 总存储 777.6 TB 的场景下,扩容一台 Broker 后完成重平衡需要 43 小时。

Let’s explore an example of an OSS Kafka cluster with three brokers [0, 1, 2]. The cluster retains messages for 30 days and receives 100 MBps on average from its producers. Given a replication factor of three, the cluster will retain up to 777.6 TB of storage, or about 259.2 TB per broker with equal balance.

Now when we scale the cluster by one broker, we need to bring the new machine up to speed. Assuming perfect data balancing, this means the new broker will be storing 194.4 TB (¾ of 259.2 TB), which will need to be read from the existing brokers. Assuming the full bandwidth was available for replication, it could take 43 hours using open source Kafka.

AutoMQ Kafka 扩缩容的运维效率是 Apache Kafka: 1 / ((AutoMQ Kafka: 1min 探测 + 1min 扩缩容 + 1min 流量重平衡) / (OSS Kafka: 43小时重平衡)) = 860x。

运维人员可以像普通业务应用一样运维 AutoMQ Kafka,将高风险的 Apache Kafka 扩缩容、流量重平衡操作变为低风险的自动化运维。