Skip to content
Published on

Kafka Diskless Topics(KIP-1150)是什么 — 用延迟换取的跨 AZ 成本,以及一个尚未交付的功能

分享
Authors

引言 — Tiered Storage 没能解决的成本

在云上跑过 Kafka 的人都知道账单上哪一行最痛。不是磁盘,是网络。

KIP-405 Tiered Storage 已经被广泛使用,它把非活跃 segment 下沉到对象存储,大幅降低了保留成本。但 KIP-1150 的动机部分点出的正是这里 — Tiered Storage「并没有消除对活跃 segment 进行复制与持久化存储的需求,而这正是当今超大规模云厂商环境下 Kafka 运维者面临的最大基础设施成本」。

原因在于 Kafka 的复制是 broker 对 broker 的通信,而在跨可用区(AZ)部署的集群里,这部分流量全都是跨 AZ 的。无论数据保留多久,每一个新写入的字节都会按复制扇出的份数跨越一次 AZ 边界。Tiered Storage 让「旧数据」变便宜了,却没能让「刚写进来的数据」变便宜。

2026 年 3 月 2 日,Apache Kafka 社区批准了一项正面瞄准这个问题的提案:KIP-1150:Diskless Topics。

被批准的,与没被批准的

先澄清一个误解:批准不等于交付。

KIP-1150 正文的 Proposed Changes 部分开篇就写道 — "This KIP will not require any changes to the codebase or documentation upon acceptance."(本 KIP 一旦被接受,不要求对代码库或文档做任何改动)。也就是说,批准并不会改动一行代码。接下来的句子说得更明确:批准这个 KIP,社区达成的是「关于这个功能的必要性以及终端用户需求的共识,而不是关于具体实现细节的共识」。

Kafka 社区把这类提案称为「元 KIP」,或者「动机型 KIP」。这是有先例的。移除 ZooKeeper、引入 KRaft 的 KIP-500 走的就是同一条路子 — 先就大方向达成一致,再把真正的设计拆分到后续的 KIP 里。

所以,如果把现状写准确,是这样的。

KIP-1150: Diskless Topics       Accepted (2026-03-02)   <- 仅批准了方向
  ├─ KIP-1163: Diskless Core         Under Discussion    <- 真正的设计
  ├─ KIP-1164: Diskless Coordinator  Under Discussion    <- 真正的设计
  └─ KIP-1165: Object Compaction     Under Discussion (Re-Opened)

Apache Kafka 最新版本: 4.3.1 (2026-06-25 released) -> 没有 Diskless

也就是说,截至 2026 年 7 月,Diskless Topics 不在任何一个 Kafka 版本里。目标发布版本号也还没有公布,社区只是就方向达成了一致。

为了给出一个时间尺度上的参照 — 据 Aiven 的 Josep Prat 在批准后回顾文章中所说,KIP-405 Tiered Storage 从最初的草案到被批准,花了 2 年 3 个月(2018 年 12 月 14 日 → 2021 年 2 月 18 日)。而那还只是「到批准为止」的时间。KIP-1150 本身从 2025 年 4 月 16 日发布第一个版本到被批准,只花了大约十个半月,但这是拆分策略带来的速度,不是实现变快了。借用同一篇文章的说法:「KIP-1150 获批之后,我们画出了路线,抵达了大本营。攀登现在才刚刚开始。」

成本计算的起点 — 跨 AZ 流量

KIP-1150 的动机部分只给出了三行数字,原样照搬如下。

最后一行很关键。三大云厂商里只有两家对跨 AZ 流量收费。如果你在 Azure 上运行,Diskless 的核心经济逻辑就不成立。 KIP 也承认这一点,并另外列出了即便去掉网络成本也仍然存在的收益 — 需要存到磁盘上、在 broker 之间做再平衡的数据变少了,集群的可扩展性因此变好;对象存储也比本地磁盘更耐用。这是诚实的说法,但如果一个团队的主要动机就是省钱,那在 Azure 上就得重新打一遍算盘。

Diskless 承诺要消除的东西有两项。

  • 消除因复制产生的跨区数据传输成本
  • 消除生产者的跨区入向流量成本,以及消费者的跨区出向流量成本

第二项很显眼。它瞄准的不只是复制流量,还有客户端流量。要理解这怎么可能实现,就得看架构。

架构 — WAL Segment 与 Diskless Coordinator

KIP-1163: Diskless Core 承载了真正的设计。核心转变只有一个 — 把数据与元数据分离

在经典 topic 中,接收 Produce 请求的 broker 要做六件事:验证数据、分配 offset 与时间戳、把 offset 注入批次数据、写入持久化存储、等待复制完成、返回响应。在 Diskless 中,其中 offset 与时间戳的分配被转移给了「Diskless Coordinator」,而 offset 的注入则交给每个副本自己负责。

Produce 路径是这样流转的。

1. 生产者把 Produce 请求发给任意一个 broker(不必是 leader)
2. broker 把请求先缓冲起来(直到达到大小或时间上限)
3. 一旦达到上限,broker 就创建一个 WAL Segment
   -> 来自多个 topic/partition 的批次会被混装进同一个对象
4. 把 WAL Segment 上传到对象存储(耐久性在这一步得到保证)
5. broker 把 batch coordinates 提交给 Diskless Coordinator
6. Coordinator 分配 offset、持久化坐标,并返回响应
7. broker 对绑定在该对象上的所有 Produce 请求做出响应

这里有一个设计决策直接影响成本。与经典 segment 不同,WAL Segment 会把多个 partition 的数据混装进同一个对象。用 KIP 的说法,这是「为了把对象存储的写操作成本控制在合理水平所必需的」— 如果每个 partition 都单独建一个对象,PUT 请求数会随 partition 数量成比例爆炸。但代价也随之而来 — 因为一个对象里混着多个 topic 的数据,物理删除就变得棘手。KIP-1163 用逻辑删除解决了这个问题,并诚实地把出于合规目的的物理删除时间点定在「比最长的 roll time 稍长一点」的位置。

"没有磁盘"这句话的真正含义」,KIP-1150 也亲自做了说明。Diskless 的意思是 broker 磁盘不再作为用户数据的主要耐久性存储,而不是磁盘消失了。KRaft 元数据、批次元数据、正在被复制到 Tiered Storage 中途的数据、为向消费者提供服务而准备的缓存,这些依然要用到磁盘。KIP 里有一句话说得很妙 — 「Diskless 之于'无磁盘',就像 Serverless 之于'无服务器'」。

在元数据这一侧,KIP-1164: Diskless Coordinator 有一个有意思的实现选择。Coordinator 的状态被存进一个叫 __diskless_metadata 的新内部 topic,再把这个 topic 分片到多个 partition 上,从而生成多个 coordinator。而本地状态的物化,用的是 SQLite。理由写得很明白 — 与其他 coordinator 不同,DC 的状态大小预计会达到「数百 MB,甚至几个 GB」,全部放进内存并不现实。如果 Kafka broker 里出现 SQLite 让你觉得不太寻常,这种直觉恰恰是这些 KIP 至今仍处于 Under Discussion 的部分原因。

延迟账单 — KIP-1163 自己写下的预算

现在是本文最重要的部分。Diskless 的代价是延迟,而 KIP-1163 把这笔预算毫不遮掩地写了下来。

Append latency is broadly composed by:
- Buffering: up to 250ms or 4MiB (both configurable)
- Upload to Remote Storage: P99 ~200-400ms, P50 ~100ms
- Batch Coordinates Commit: P99 ~20-50ms, P50 ~10ms (取决于批次数量)

We are aiming for a Produce request latency of P50 ~500ms P99 ~1-2 sec

读法很重要。这是一个目标值,而不是测量值。KIP 的原文用的是 "We are aiming for",我不会把它读成「实测出来就是这样」。毕竟上游还没有实现,也就谈不上有测量值。

不过这份预算依然揭示了结构。目标 P50 约为 500ms,其中最多 250ms 是缓冲。这意味着大约一半的延迟并不是因为存储慢,而是来自「选择了等待」这个决定本身 — 要摊薄对象存储的写操作成本就得攒批次,攒批次就得等。这是从经济法则里长出来的延迟,不是物理法则。

剩下的一半属于物理层面。KIP-1163 写道「远程存储的延迟可能高于本地磁盘,这会增加 Kafka 请求以及端到端的数据延迟」,WarpStream 的文档也说了同样的话 — 「在对象存储里创建一个文件,相对于本地磁盘写入而言,是一个延迟相对较高的操作」。

那这 500ms 该拿什么来比较呢?KIP 和厂商文档都没有给出经典 Kafka Produce 延迟的基准值,所以我在这里也不会替它们编一个数字出来。真正的比较对象是你自己现在的集群 — 你的生产者现在是多少毫秒收到响应的,这个数字只存在于你自己的仪表盘上,把它和 500ms 摆在一起,才是唯一有意义的比较。

KIP-1163 并没有回避这个权衡,反而把它变成了一条设计原则。Diskless topic、经典 topic、tiered topic 「共存于同一个集群」,让应用开发者可以「按 topic 粒度在延迟和成本之间做取舍」。按 KIP 对数据流的描述,低延迟数据继续走经典 topic,高延迟容忍度的数据则流向 Diskless 摄取引擎。也就是说,这不是一个取代 Kafka 的功能,而是给 Kafka 「多加了一个旋钮」的功能。

该如何看待厂商给出的数字

已经有商业产品把 Diskless 这个思路放到生产环境里跑起来了,比如 WarpStream、Buffstream、Confluent Freight Clusters、Redpanda Cloud Topics 等等。它们公开的数字,是「一个基于 S3 的日志引擎实际能跑出多少延迟」这个问题上唯一的实测参考点,但请别忘记:这一切全都是厂商自测

WarpStream 的官方文档算是比较坦诚的一个。它的性能调优文档写道 — 「WarpStream Agent 没有本地磁盘,直接把数据写入对象存储。在对象存储里创建一个文件,相对于本地磁盘写入而言,是一个延迟相对较高的操作。举个例子,据我们的经验,在 S3 上写入一个 4MiB 文件的 P99 延迟大约是 400ms。」(Tuning for Performance)「据我们的经验(in our experience)」这个限定语原文里就明明白白地写着。

这份文档接下来讲的内容更实用。要在 400ms 延迟之上跑出吞吐量,按利特尔法则就需要并发。照搬文档自己给的例子 — 要在 1MiB 批大小下达到 1GiB/s 的写入吞吐量,就需要同时有 400 个 Produce 请求在途。文档还直接断言:「未处理请求数不够,是使用 WarpStream 时写入吞吐量偏低的头号原因」。迁移到基于 S3 的引擎,意味着客户端调优这件事本身的性质都变了。

还有进一步降低延迟的办法,但不是免费的。WarpStream 的 S3 Express 文档 说「配合缩短批次超时时间,S3 Express 可以把 Produce 请求的 P99 延迟降到 150ms 以下」。但同一份文档也列出了代价 — S3 Express One Zone 顾名思义只存在单个 AZ 里,所以 WarpStream 必须跨多个单区桶的仲裁组做复制,而且 S3 Express 的存储成本,在考虑复制之前,就已经是普通对象存储的约 7 倍。因此推荐的配置是只把摄取环节放在 S3 Express 上,压缩(compaction)则下沉到普通桶。这又回到了最初那句话:想买延迟,就得花钱。

另一方面,也有需要谨慎解读的数字。Aiven 那篇批准后回顾文章里,相关资料卡片上挂着一句「TCO 最高可削减 80%」。这是「厂商自身的说法」,而这篇文章完全没有给出这 80% 到底算了什么、又排除了什么的依据 — 是什么样的工作负载、哪个云、多大的复制因子、多长的保留期、有没有算上计算成本,一概没有说明。它只是宣传文案上挂着的一个上限(「最高」)。Aiven 既是 KIP-1150 的主要作者,也是靠托管 Kafka 盈利的公司(文章本身倒是坦诚地披露了这层利益关系)。流式厂商给出的 TCO 测算尤其容易带有自利倾向,所以这类数字在你用自己的工作负载验证之前,最多只能当作一个方向性的指示灯。

悄悄碎掉的地方

KIP-1150 表示 Diskless topic 意在与经典 topic「语义上可互换」,并列出了对顺序保证、幂等性、事务、消费者组、队列/共享组、tiered storage 的全面支持。这些大多可能是真的,但仔细读设计文档,还是能看到几处不那么平滑的边角。

队列(共享组)拿不到完整的成本收益。 KIP-1163 直接写明 — ShareFetch 请求只能由 share-partition 的 leader 处理,而这个 leader 和 partition leader 在同一个地方。因此「队列消费者必须把 ShareFetch 请求发给 partition leader,无法始终享受到消除跨区消费者流量带来的好处」。消除跨区出向流量这条承诺出现了一个例外,而针对队列功能的机架感知优化,也被推出了这个 KIP 的范围之外。

ISR 的含义变了。 在 Diskless 里,「in-sync replica」不再意味着与 leader 同步,而是「与 Diskless Coordinator 同步」的意思 — 因为 Coordinator 才是真源。KIP-1163 点出的推论很尖锐 — leader 本身也只是众多副本之一,因此leader 自己也可能处于 out-of-sync 状态。一旦如此,leader 就无法高效地完成自己把 segment 卸载到 tiered storage 的职责,而且和其他 out-of-sync 副本一样,不建议从 leader 上读取数据。这是一个长期运维 Kafka 的人的直觉会在此被折一下的地方。顺带一提,即便副本之间不再做 broker 间复制,副本依然会向 leader 发送 FetchRequest — leader 会返回一个不带任何记录的空响应,这一来一回,如今只剩下 ISR 追踪这一个用途。

旧版客户端得走一条弯路。 新版客户端通过 MetadataRequest v14 发送机架信息,并借此得知哪些 topic 是 Diskless、该向哪个 broker produce 更合适。但对旧版本或第三方客户端,KIP-1163 给出的方案是在 client ID 后面附加一个机架标识符。

client.id = "my-app,diskless_rack_id=use1-az4"

broker 会读取这个字符串,然后把对应机架的副本当作 leader 一样填进响应里。这确实能用,但正如 KIP 自己承认的,这样做会挡住只有真正的 leader 才能处理的 ShareFetch。于是就跟着一条运维准则 — 「给生产者和普通消费者设置 diskless_rack_id,但不要给共享消费者设置;后者在代码上必须是一个独立的实例」。不优雅,他们自己也清楚这一点。

那么,你该等吗

判断标准可以这样归纳。

大概率值回成本的情况

  • 你在 AWS 或 GCP 上运行,且吞吐量足够大,跨 AZ 复制流量在账单上是实实在在的一项。
  • 工作负载对延迟宽容 — 比如日志采集、指标、分析流水线、批量式摄取这类场景,几百毫秒的 Produce 延迟没有任何意义。
  • 吞吐量高,且每个 partition 的数据足够厚,批次能自然攒满。

属于过度设计、甚至有害的情况

  • 你在 Azure 上运行。没有跨 AZ 收费,核心经济逻辑就不存在了。
  • 延迟是产品的硬性需求。目标值是 P50 500ms 的路径,装不下订单成交或用户请求这类路径。
  • 吞吐量低。流量少,跨 AZ 成本本来就低,你却要原原本本地承受缓冲带来的延迟。
  • 队列/共享组是你的主要使用模式。上面说的那个例外会正面撞上你。
  • 而且你现在就需要它。 这是最现实的排除条件。

最后一条我想再强调一遍。截至 2026 年 7 月,这个功能并不存在。只有方向被批准了,两份设计 KIP 还在讨论中,也没有目标发布版本。如果你现在的跨 AZ 账单就在痛,可选项是商业产品(比如 WarpStream)、Aiven 开源出来的实验性分支 Inkless,或者靠现有手段(比如单机架 topic)硬扛过去。KIP-1150 在 Rejected Alternatives 一节里明确否决了单机架 topic 这类现有变通方案,理由是它们「在耐久性、可用性、语义和易用性方面,强迫应用各自做出妥协」— 讽刺的是,这些妥协恰恰是你现在唯一能选的东西。

剩下的路

KIP-1150 之所以有意思,与其说是技术问题,不如说更接近政治问题。

Rejected Alternatives 一节的最后一项是「Do Nothing」,它的论证异乎寻常地坦率 — 如果什么都不做,这将成为「上游实现里缺失的单项最大功能」,把高规模、上云的用户推向 Kafka 的替代品,甚至可能让 Kafka「彻底失去对 Kafka 协议的话语权」。事实上,过去几年冒出来的那些云原生、兼容 Kafka 协议的产品,没有一个是开源的。KIP-1150 正是上游对这股潮流的回应。

这个回应有多认真,从同时冒出三个竞争提案这件事上就能看出来 — 除了 KIP-1150,KIP-1176(Tiered Storage for the Active Log Segment)和 KIP-1183(Unified Shared Storage)也提交到了同一个领域,最终以 KIP-1183 的作者们(Slack)撤回自己的提案、转而正式支持 KIP-1150 收场。投票在 2026 年 1 月 9 日重新开始,3 月 2 日通过,据 Aiven 的统计,获得了 9 张 binding 票和 5 张 non-binding 票。

接下来要做的,是真正把 KIP-1163 和 KIP-1164 推过去。再往后,还有 KIP-1150 留在「Further Work」里、连 KIP 都还没有的一些条目 — 经典 topic 与 Diskless topic 之间的类型转换、broker 角色专精化(专用于 produce/consume/coordination/compaction 的 broker)、在高延迟环境下为提升单生产者吞吐量而做的并行 Produce 处理、Iceberg 格式,以及通过元数据复制实现的多区域 active-active。最后这两项一旦成真,触及的将是 Kafka 身份认同本身的问题,但眼下也只是清单上的一行字而已。

结语

归纳一下:Tiered Storage 让旧数据变便宜了,却没有动活跃 segment 的复制流量,而这恰恰是超大规模云厂商环境下 Kafka 最大的一项基础设施成本。KIP-1150 是社区就一个方向达成的共识 — 以对象存储作为真源来消除这项成本 — 而且只是方向。

代价是清楚的,设计文档也没有藏着掖着:目标 Produce 延迟是 P50 约 500ms,P99 约 1~2 秒。其中大约一半,是为了摊薄对象存储 PUT 成本而攒批次所花的时间。所以 Diskless 不是「更好的 Kafka」,而是「一个可以按 topic 单独调节的旋钮」— 需要低延迟的 topic 留在经典模式,只有对延迟宽容的大流量 topic 才会被送去 Diskless,这是设计者们描绘的图景。

而这个旋钮,现在还不在你手里。它不在 Kafka 4.3.1 里,什么时候会来也还没有公布。所以现在该做的不是迁移计划,而是测量 — 你的跨 AZ 流量到底占账单的多少,你的生产者能不能扛住 500ms。不知道这两个数字,这个功能就算到货了,你也没法判断该不该用它。账单先于功能,而不是反过来。

参考资料