Kafka 分区数到底设几个:吞吐量、顺序性与 rebalance 代价的取舍
发布时间:2026/10/16 3:09:03 锦皓数字建站

我不会起名字322· 后端 / 算法 / 数据库 技术栈 力扣 Hot100 Go 项目 Redis MySQL文章目录Kafka 分区数到底设几个吞吐量、顺序性与 rebalance 代价的取舍一、为什么这个问题没有标准答案二、先算吞吐分区数决定并行度上限怎么估需要的分区数生产端也一样三、再算顺序性分区数会破坏 key 的顺序四、然后算 rebalance 代价五、一个实用的决策流程常见规模参考六、分区数只能加不能减七、还有几个容易忽略的点分区数最好是消费者数的整数倍副本数也要一起考虑消息 key 的分布要均匀用自定义分区器解决热点八、带走物Kafka 分区数到底设几个吞吐量、顺序性与 rebalance 代价的取舍一、为什么这个问题没有标准答案分区数同时影响四件事而且方向不一致维度分区多了分区少了吞吐↑ 更多并行↓ 并行度受限顺序性↓ 同一 key 分散↑ 更容易保证rebalance 代价↑ 分区多重分配慢↓端到端延迟↑ 分区多更多 batch 等待↓没有最优解只有在你的约束下的平衡点。而且这四个维度的权重取决于你的业务是什么类型。二、先算吞吐分区数决定并行度上限一条硬规则一个分区在同一时刻只能被一个消费者线程消费。所以消费并行度上限 min(分区数, 消费者实例数 × 每实例线程数)分区数 消费者数时多出来的消费者完全空闲。怎么估需要的分区数先算目标吞吐目标吞吐 峰值消息量条/秒× 单条处理耗时秒 需要的并行度举例峰值 5000 条/秒单条处理 20ms0.02s → 需要 5000 × 0.02 100 个并行处理能力如果每个消费者线程能跑满那就需要100 个分区。但现实中要考虑两个折扣单线程不可能 100% 跑满有 IO 等待实际并行度打个 1.5~2 倍余量消费峰值 ≠ 生产峰值消费可以滞后一点不必完全实时。所以实用公式分区数 ≈ 峰值TPS × 单条耗时 × 1.5生产端也一样生产者可以往多个分区并行写分区数太少会限制生产吞吐。经验值单个分区的生产吞吐大约 1~10 MB/s取决于消息大小和压缩。三、再算顺序性分区数会破坏 key 的顺序关键机制默认分区器是hash(key) % 分区数。这意味着分区数一变同一个 key 的落点就变了分区数 3order_100 → hash % 3 1 分区数 4order_100 → hash % 4 0扩分区的瞬间顺序性会被短暂破坏。正在途中的消息在旧分区新消息在新分区两条不同的消费者可能以不同速度消费导致后发的先被处理。如果你的业务严格依赖 key 的顺序比如订单状态机分区数不要频繁变非扩不可时选低峰期 消费无积压的时候做或者一开始就按未来的峰值预留分区数下面会讲代价。四、然后算 rebalance 代价分区越多rebalance 越贵分配计算更慢分区多coordinator 计算分配方案耗时更长停止消费的时间更长rebalance 期间整个组停止消费分区越多恢复后要重新拉取的 offset、要重建的 fetch 请求越多元数据更大消费者要维护更多分区的状态。经验值分区数 50 rebalance 影响很小 分区数 50~200 能感知到但可接受 分区数 500 rebalance 代价明显要谨慎另外还有一个隐藏成本每个分区在 broker 上都是一个目录 若干文件句柄。一个 broker 上几千个分区会导致启动时要加载大量日志段恢复很慢文件句柄占用高选举 leader 变慢。Kafka 官方的建议是单个 broker 上的分区数不超过 4000整个集群不超过 200000。五、一个实用的决策流程1. 先算吞吐需求分区数 ≥ 峰值TPS × 单条耗时 × 1.5 2. 检查顺序性约束 ├─ 依赖 key 顺序 → 分区数定下来就别轻易改预留一点余量 └─ 不依赖顺序 → 可以更自由地扩 3. 检查 rebalance 敏感度 ├─ 消费者经常重启/发布 → 分区数别太大 200 └─ 消费者稳定 → 可以放宽 4. 检查集群规模 单 broker 分区数 4000常见规模参考场景建议分区数小流量100 TPS3~6中等几百 TPS12~24较大几千 TPS48~96高吞吐日志类不要求顺序100~200大多数业务 12~48 就够了。我见过很多 topic 设了 100 分区但实际只跑了几个消费者纯属浪费。六、分区数只能加不能减这是一个必须知道的硬限制Kafka 不支持减少分区数。# 只能加kafka-topics.sh--alter--topicorder--partitions24# 减会报错kafka-topics.sh--alter--topicorder--partitions6# Error: The number of partitions for a topic can only be increased原因减少分区意味着要决定被删掉的分区里的消息去哪而已经消费的 offset 无法回退。所以定分区数时要保守一点宁可略多也不要一开始就卡死但要平衡 rebalance 代价。扩分区是有代价的顺序性、rebalance但至少可行。如果真的要减只能新建一个 topic把数据迁过去再切流量。这是大工程。七、还有几个容易忽略的点分区数最好是消费者数的整数倍分区 12消费者 4 → 每个消费者 3 个分区均匀 分区 12消费者 5 → 4 个消费者拿 2 个1 个消费者拿 4 个不均不均的后果拿多的那个消费者成为瓶颈而且扩容第 5 个消费者之前前 4 个的负载一直不均。副本数也要一起考虑分区数 × 副本数 实际partition 总数。分区 24 × 副本 3 72 个 partition 副本分布在集群里副本多会增加存储成本和同步开销但提升可靠性。副本数建议 3能容忍 1 个 broker 挂掉。消息 key 的分布要均匀hash(key) % 分区数只有在key 分布均匀时才均匀。如果 90% 的消息都是同一个 key比如某个大客户的 ID那么对应分区会成为热点——加分区也解决不了。这种情况要改 key 设计比如加随机后缀打散或者用自定义分区器。用自定义分区器解决热点// sarama 自定义分区器给热点 key 打散typeshardPartitionerstruct{topicstring}func(p*shardPartitioner)Partition(msg*sarama.ProducerMessage,nint32)(int32,error){key,_:msg.Key.Encode()// 对热点 key 加随机后缀打散到多个分区ifisHotKey(string(key)){returnint32(rand.Intn(int(n))),nil}h:fnv.New32a()h.Write(key)returnint32(h.Sum32()%uint32(n)),nil}config.Producer.Partitionerfunc(topicstring)sarama.Partitioner{returnshardPartitioner{topic:topic}}注意打散热点 key 会破坏该 key 的顺序性——这是又一次取舍。八、带走物决策清单1. 算下限分区数 ≥ 峰值TPS × 单条耗时 × 1.5 2. 看顺序性依赖 key 顺序 → 定完就别改扩分区会短暂破坏顺序 3. 看 rebalance消费者经常重启 → 分区数控制在 200 以内 4. 看集群单 broker 分区数 4000 5. 尽量让分区数是消费者数的整数倍 6. 记住分区只能加不能减一开始就留点余量 7. 检查 key 分布热点 key 加分区没用要改 key 或自定义分区器一句话结论分区数不是一个性能参数而是一个并行度 × 顺序性 × rebalance 代价的三维取舍而且它只能加不能减所以第一次定值时就要把未来的峰值算进去。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。