minio访问万亿级 Kafka 消息规模下的降本增效之旅
京东内部使用基于 Apache Kafka 构建的 JDQ 来支持其平台业务。JDQ 是京东集团大数据平台统一的实时数据总线,赋能集团内部京东零售、物流、科技、健康、安联等 40 多个一级部门,搜索推荐、广告、点击流、实时大屏等的业务线。JDQ 当前集群规模多达 6000 多个节点,每天产生的记录数达 15 万亿,峰值出带宽达到
JDQ 平台采用 Kubernetes 进行有状态服务编排,通过 StatefulSet 控制器管理整个集群,支持多种存储方案和服务访问方式。该平台可部署在私有云、公有云以及京东内部的 Kubernetes 平台上。随着公司整体技术架构向基于 Kubernetes 的云原生架构演进,JDQ 在 Kubernetes 上的运行效率、成本和弹性都面临新的挑战。
CubeFS(原名 ChubaoFS)是一款新一代云原生开源存储系统,是云原生计算基金会(CNCF)的毕业项目。该开源项目由社区和 OPPO 等多家公司共同维护和发展,持续在云存储、高性能计算等领域优化演进。京东作为该项目的早期发起者,在内部大规模应用,支撑了海量离在线业务的稳定运行。
CubeFS 支持 S3、HDFS 和 POSIX 等访问协议,广泛适用于大数据、AI/LLMs、容器平台、数据库和中间件等场景,提供存储与计算分离、数据共享和分发等能力。
京东 JDQ 底层存储采用支持 S3 协议的 CubeFS 对象存储。CubeFS 通过多副本机制来保证数据持久性,而 Kafka 则使用 ISR 多副本机制实现相同目的。Apache Kafka 诞生于十几年前,其架构专为 IDC 物理机部署而设计。Kafka 将数据存储在本地磁盘上,并通过多副本的 ISR 机制来确保数据持久性。这种设计在当时是合理的。然而,随着云计算时代的到来,基于 S3 等对象存储的共享存储架构逐渐兴起,Kafka 的传统架构显得不够优化。以京东为例,当 Kafka 直接部署在 CubeFS 上时会产生大量数据冗余:针对 Kafka 的一份写入数据,由于 ISR 需要进行副本复制,真正存储到 CubeFS 上以后,考虑到 CubeFS 内部的多副本机制,实际存储了 9 份数据,其中约 66.67%(6/9)的存储空间被不必要的数据冗余占用,造成了严重的资源浪费。
此外,Kafka 层面的副本复制以及写远程 CubeFS 还会消耗额外的网络带宽。这导致在当前架构下,Kafka 的 ISR 机制反而造成了存储和网络带宽资源的过度使用,最终增加了总体成本。下图展示了 Kafka 部署在 CubeFS 上时,冗余数据是如何产生的。其中虚线的数据块则是冗余的数据副本。
Kubernetes 为企业带来了诸多益处,尤其是通过容器化和 Pod 抽象显著提升了硬件资源利用率,并降低了成本。在全面 Kubernetes 化的背景下,像 Apache Kafka 这样的核心基础软件也需要部署在 Kubernetes 上,以充分利用其资源优化优势。京东内部已将 50% 的物理节点上的 Kafka 集群迁移至 Kubernetes,在这个过程中我们深切体会到了 Kafka 本身架构在 Kubernetes 上运行所带来的挑战。Apache Kafka 采用存算一体的 Shared-Nothing 架构,其计算节点 Broker 与本地存储紧密耦合,这使得其难以在 Kubernetes 上实现灵活的扩缩容。
由于 Kafka 的架构不符合 Kubernetes 原生设计理念,其扩缩容操作在 Kubernetes 上成为了一个需要人工介入的高风险操作。在这种限制下,Apache Kafka 只能作为与 Pod 绑定的静态资源部署。Kubernetes 无法根据集群资源利用率来自动扩缩容节点和调度 Pod,因此也就无法发挥其优势。
在寻求解决京东内部 Kafka 挑战的调研过程中,我们发现了 AutoMQ[1] 这一优秀产品。AutoMQ 采用计算与存储分离的共享存储架构,在确保与 Apache Kafka 完全兼容的同时,可将数据存储到兼容 S3 协议的对象存储之上,从而显著降低成本并提升效率。
100% 完全兼容 Kafka,利于迁移:鉴于京东内部拥有大规模的 Kafka 集群及其周边基础设施,AutoMQ 的完全兼容性确保了现有业务无需任何代码改造和配置修改即可无缝迁移,同时可充分利用现有 Kafka 生态系统。
数据卸载至云存储,显著降低存储、带宽资源:AutoMQ 基于 WAL 和对象存储构建的共享存储架构实现了计算与存储的完全分离。不同于 Apache Kafka 的 ISR 多副本机制,AutoMQ 将数据持久性直接委托给 S3/CubeFS 等对象存储服务。这种设计使得写入 Broker 的数据在 CubeFS 层面仅产生 3 份副本,大幅降低了存储资源消耗。由于采用单一 Leader Partition 设计,AutoMQ 还节省了传统 Kafka Replica 写入远程 CubeFS 产生的网络带宽开销。
极速弹性、自动平衡:AutoMQ 架构无需像 Kafka 那样迁移分区数据就能完成扩缩容。迁移分区只需更新元数据,在 1 秒左右即可完成。AutoMQ 内置的 Self-Balancing 组件持续监控集群状态,实时进行业务无感知的分区迁移和调度,确保集群流量和 QPS 始终保持均衡。凭借这种弹性优势,AutoMQ 能与 Kubernetes 平台的 Autoscaler、Karpenter 等工具完美配合,根据负载自动进行集群扩缩容,充分发挥 Kubernetes 的潜力。
CubeFS 单目录下文件数过多优化:CubeFS 同时兼容 S3 和 Posix 协议访问,使用 AutoMQ 通过 S3 协议往 CubeFS 写入大量数据后,单个目录下可能会产生大量的子目录和文件,而这些大量的子目录为了兼容 Posix 协议访问,会对 CubeFS 后端集群的元数据管理造成较大压力;并且 AutoMQ 在执行 compaction 时使用 KEEP_DATA 策略,从 kraft 中删除 metadata,但是底层 object 文件依然存在,这些文件会使得 CubeFS 单目录下存在过多的子目录;京东优化调整了 AutoMQ 的 MINOR_V1 参数后,将 compaction 操作通过物理合并,能将存储在 CubeFS 的 object 文件数量降低 90%,从而降低 CubeFS 后端集群的元数据管理压力。
CubeFS 空目录优化:CubeFS 在创建对象文件时,会将文件前缀转换成目录,AutoMQ 在创建数据主存对象文件时,也会在 CubeFS 集群上创建对象文件的前缀目录,而对象文件删除后,相应的前缀目录存在没有删除的情况,这样造成了 CubeFS 上面存在大量未清理的空目录;在通过优化 Object Node 对前缀目录的元数据标记后,能级联删除对象文件相应的前缀目录,从而消除了 AutoMQ 基于 CubeFS 产生的空目录问题。
CubeFS S3 请求接口兼容扩展:CubeFS 目前兼容 S3 协议的读写请求访问,但是也有个别 S3 SDK 的接口目前还没有兼容支持,比如 AutoMQ multipart object 在超过 32MB 之后调用的 S3 UploadPartCopy 接口,目前还没有兼容支持,后续京东规划会根据业务场景的需求进行兼容支持。
当前,京东采用的是 AutoMQ S3 WAL [2] 的模式。AutoMQ 的架构设计中对于 WAL 进行了高度的抽象,可以将不同的存储介质作为 WAL。在京东的场景中,我们将 CubeFS 本身作为了 WAL,不再依赖本地存储,整体的架构变得十分的简洁、高效。
下图展示了京东内部一个 AutoMQ 生产集群的核心指标。这个集群在采用 AutoMQ 新架构后,取得了以下成效:
集群存储成本降低 50%,带宽成本降低 33%:得益于 AutoMQ 的云原生架构,显著降低了 Kafka 集群在存储和网络带宽方面的资源需求,大幅节省了成本。
集群在 Kubernetes 上扩容效率由小时级别提升到分钟级别:使用 AutoMQ 后,部署在 Kubernetes 上的 Kafka 扩缩容不需要大量的拷贝迁移数据,将扩缩容的时效提升到了分钟级别。AutoMQ 集群能够快速动态调整容量,从容应对大促、秒杀等电商场景,不仅减轻了运维负担,还避免了为应对峰值而过度配置资源的浪费。
AutoMQ 作为一款以“云优先”理念设计的新一代 Kafka 与京东业务全面上云、云原生化的步调一致。在未来,我们将在保证集群稳定、高可用的前提下,进一步推广和深化 AutoMQ 在京东的应用,促进数据基础设施全面云化、云原生化并且进一步降低数据基础设施的成本、提升效率。