背景#

我们的项目使用 Confluent Cloud 托管 Kafka 集群,在上线前需要确定每个 topic 的分区(partition)数量。Kafka 的分区数只能增加不能减少,因此更适合在初始阶段先做一轮带假设前提的评估。

本文记录这一评估过程。

业务规模#

基础数据 (单 Topic)#

参数 数值
单 Topic 日均消息量 4 亿条
活跃用户数 ~200 万
人均日均交易笔数 200 笔
每笔交易产生消息数 1 条
Topic 数量 约 60 个
集群日均总消息量 约 240 亿条

单 Topic RPS 推导#

单 Topic 全天平均 RPS = 4亿 ÷ 86,400秒 ≈ 4,630

交易流量并非均匀分布。假设流量集中在约 8 小时的活跃窗口内:

单 Topic 活跃时段平均 RPS = 4亿 ÷ (8 × 3,600秒) ≈ 13,900

活跃窗口内还存在早晚高峰,峰值通常为活跃时段均值的 2–3 倍:

峰值系数 单 Topic 峰值 RPS
2x ~28,000
3x ~42,000

以 3x 峰值系数估算,单 Topic 峰值约为 4.2 万 RPS

消息规格#

参数 数值
消息格式 JSON
压缩前大小 ~1 KB
压缩算法 Snappy
压缩后大小 ~0.5 KB

分区数量评估#

评估公式#

Confluent 官方文档给出了分区数量的核心公式:

所需分区数 ≈ max(目标吞吐 / 单分区生产吞吐, 目标吞吐 / 单分区消费吞吐)

文档指出单分区吞吐量取决于 batch size、压缩算法、ack 配置、replication factor 等参数,建议在目标集群上实测。

参考来源:Choose and Change the Partition Count in Kafka — Confluent Documentation

Confluent 官方 benchmark 提供了一个参考数据点:在 3 个 Broker(i3en.2xlarge)、100 个分区、1 KB 消息、RF=3、acks=all 的配置下,集群总生产吞吐达到 605 MB/s,折合每分区约 6 MB/s。该测试的瓶颈在于磁盘 I/O,而非分区数量本身。

参考来源:Apache Kafka Performance — Confluent Developer

需要注意,Confluent Cloud 使用自研的 Kora 云原生引擎。Confluent 在自家材料里给出的结论是,其吞吐和延迟表现优于原生 Apache Kafka,因此上述 benchmark 更适合作为一个偏保守的下限参考。

参考来源:Kafka Latency Comparison: Confluent Cloud vs DIY Apache Kafka — Confluent Blog

吞吐量压力分析#

按单 Topic 峰值 4.2 万 RPS 计算吞吐量:

单 Topic 峰值吞吐 = 42,000 × 0.5 KB ≈ 21 MB/s

套用公式,以 Confluent benchmark 中的 6 MB/s/分区作为保守基准:

生产端:21 MB/s ÷ 6 MB/s ≈ 4 个分区

实际生产环境中,通过调优 batch.size 和 linger.ms,单分区吞吐还有继续提升的空间。因此 按这组假设来看,6 个分区在吞吐层面很可能已经有余量

但分区数量不仅关乎吞吐,还决定了 Consumer 的最大并行度——一个 Consumer Group 中,最多只能有与分区数相同数量的 Consumer 实例同时消费。

同时需要注意,Confluent Cloud 文档指出分区数增加会带来延迟上升的 trade-off:更多分区意味着 broker 之间的 replication 耗时更长,消息 commit 时间变长,最终影响端到端延迟。因此分区数量不应无限制增加。

参考来源:Optimize Confluent Cloud Clients for Latency — Confluent Documentation

6 个 vs 12 个分区#

考虑到我们的消息处理逻辑(Consumer 端)可能存在复杂的 I/O 操作(如数据库写入),单实例的处理速度往往是瓶颈。

考量维度 6 个分区 12 个分区
吞吐量(按 6 MB/s/分区保守估算) 36 MB/s(vs 21 MB/s 需求,余量 ~1.7x) 72 MB/s(余量 ~3.4x)
Consumer 最大并发数 6 个实例 12 个实例
Consumer 均匀分配(可整除的实例数) 1, 2, 3, 6 1, 2, 3, 4, 6, 12
未来流量增长/波动容忍度 一般 相对更从容

12 个分区在保证吞吐余量的同时,提供了更灵活的 Consumer 扩容空间。

成本影响#

我们有约 60 个 Topic,每个 Topic 均配置 12 个分区:

方案 总分区数
6 分区 × 60 topics 360
12 分区 × 60 topics 720
12 分区 × 100 topics (预留扩充) 1,200

Confluent Cloud 计费模式#

Confluent Cloud 存在两种计费模式(取决于账户创建时间):

旧模式(2024年4月16日前创建的账户): 按 partition 数量直接计费。Standard 套餐包含 500 个免费分区,超出部分按小时收费。720 个分区超出 220 个,会产生额外费用。

新模式(2024年4月16日后创建的账户): 改用 eCKU (Elastic CKU) 计费,不直接按分区数量收费。分区数量通过占用集群容量间接体现在 eCKU 消耗上。

参考来源:Confluent Cloud Cluster Types

以旧模式 Standard 套餐为例,额外 360 个分区(从 360 增加到 720)按 $0.0015/partition/小时估算,月增约 $238。而在日均 240 亿条消息的规模下,集群主要费用更可能集中在 eCKU 流量消耗、存储空间和跨可用区网络流量上,分区的边际成本在整体账单中的占比相对较小。

Consumer 连接模型#

一个常见误解是:1 个 Consumer 消费 12 个 partition 需要 12 个 TCP 连接。

实际上,Kafka Consumer 连接的是持有 partition leader 的 Broker。如果 12 个 partition 分布在 3 个 Broker 上,1 个 Consumer 实例只需要 3 个 TCP 连接即可轮询所有 12 个 partition。

我们的场景(每个 topic 1 个 Consumer,60 个 topic):

来源 估算连接数
60 个 Consumer × ~3 连接/Consumer ~180
Producer 连接 ~60–180
管理/监控 ~10–20
合计 ~250–380

这一连接数对 Confluent Cloud 的 Basic 和 Standard 套餐来说通常不像主要瓶颈。分区从 6 增加到 12 也不太会显著增加连接数。

关于 Spring Boot 应用中 Kafka 连接数的详细计算逻辑和实测数据,可以参考本博客的另一篇文章:How Many Kafka Connections Does Your Spring Boot App Actually Use?

结论#

在当前这组假设下,我会先从每个 Topic 12 个分区起步。

核心逻辑:

  1. 吞吐量满足单 Topic 需求:按 Confluent 官方公式和 benchmark(6 MB/s/分区保守基准),单 Topic 峰值 21 MB/s 仅需 4 个分区。12 个分区提供了约 3.4 倍的余量。
  2. 选 12 而非 6 的理由:分区数决定 Consumer 最大并行度。对于日均 4 亿消息量的 Topic,后续单 Consumer 处理能力很可能成为瓶颈,12 个分区允许我们水平扩容到 12 个实例,且支持 1/2/3/4/6/12 等多种均衡分配组合。
  3. 规模决定了成本权重:在日均 240 亿条消息的总规模下,数据传输和存储更像是主要的成本来源。相比之下,720 个分区的管理成本(无论是旧模式的固定费还是新模式的容量占比)在总账单中的权重会小一些。
  4. 一次性架构决策:分区只能增不能减。在这组业务假设下,初期配置 12 个分区更像一项偏保守的起步配置。

参考资料#