kafka分区如何合理设置,是越多越好吗?

921 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

kafka的每个topic都可以创建很多个分区,且数量无上限,那是不是意味着随心所欲设置,越多越好?

kakfa为什么要设置分区(partition)?

kafka 设计了 分区概念,不仅拥有了高吞吐量的能力, 同时也带来了负载均衡,横向扩展等能力。当然,分区是高吞吐量的必要不充分条件,只是原因之一,通过 Partition 将 Topic 中的消息均衡保存到 Kafka 集群中不同的 Broker 中。

kafka分区机制本质就是把很大的一组队列数据进行拆分成多组队列,形成生产端和消费端的分流和并行,分流和并行就能有效提升数据流读写的吞吐。

高吞吐量

单个分区是kafka并行操作的最小单元,每个partition相当于topic的一个子通道,每个通道可以独立传输,与高速公路车道与高速公路的关系,在理想状态的情况下,partition越多 吞吐量越大。

负载均衡

发送消息时可以根据分区的数量进行数据均匀分布,使其落在不同的分区上, 这样可以提高并发写性能;同时消费的时候多个订阅者可以从一个或者多个分区中同时消费数据,以支撑海量数据处理能力,提高读消息性能。

横向扩展

不同的 Partition 尽可能的部署在不同的物理节点上,这样扩展起来非常方便;一个消费者可以消费多个分区中的数据,为了充分发挥横向扩展,就引入了消费者组来消费整个的 Topic,一个消费者消费 Topic 中的一个分区。

\

kafka如何合理设置分区数

回归到本文摘要,kafka的每个topic都可以创建很多个分区,且数量无上限,那是不是意味着随心所欲设置,越多越好?

回答肯定是否定的, 那我们如何确定partition的数量,需要参考哪些因素呢? 从哪些方面考虑呢?

  1. 根据业务特点
  2. 根据并行度

根据数据要处理的并行度来定partition个数,为了防止单个节点负载过高,可以定为跟broker数量一样,或者跟后续计算引擎要并行的数量一致。

  1. 根据经验

首先根据某个 Topic 当前接收的数据量等经验来确定分区的初始值。

  1. 根据压力测试结果

kafka官方提供了脚本方便我们针对我们的kafka集群做测试,我们可以测试当前提供的硬件条件进行压测,得出当前机器环境到底能支持多少分区数,从而达到尽量最优的方案。

生产者性能测试脚本:kafka-producer-perf-test.sh

消费者性能测试脚本:kafka-consumer-perf-test.sh

设置好topic的某个分区数,之后我们可以选择不同的参数:比如消息发送总量、单条消息大小、吞吐量、acks、消费线程数等等,这样压测之后就能得出一份测试报告,报告包含的数据有:50%/90%/95%/99%的消息处理耗时、平均处理耗时、每秒消息发送吞吐量、每秒拉取的消息的字节大小/消息数量、消费总数、再平衡时间、按消息计数/消息大小计算的吞吐量等等。

合适的增加分区数是可以提高吞吐量,但超过一定的阈值之后,吞吐量也会随之下降。如果生产上对吞吐量有一定的要求,可以在生产机器硬件条件下进行压测,得出适合你的最优分区数。

分区设置太多,会有什么影响?

在前面提到, 理想状态下, 分区越多,吞吐量越大。 但实际情况中,显然不是。那分区太多,又会又哪些方面的影响呢。

  1. 使用内存方面
  • Broker在内存中维护 了组件的分区级别缓存,分区数量越大,缓存越多。
  • 为了达到更高吞吐量,避免产生消息堆积,开启的Consumer数量也需要随分区增加;
  1. 操作系统方面
  • 每个partition会对应到磁盘的一个目录,每个日志数据段都两个index文件和一个数据文件。 每个Broker需要为每个日志段文件打开3个句柄(2个index,1个log),partition越多,占用操作系统句柄数成倍增加。

  1. 生产者到消费者延迟
  • 分区越多,副本之间需要同步的数据就越多。消息需要在所有ISR副本列表同步复制完成,才会暴露给消费者,那复制数据所花的时间就是延迟时间的主要部分。
  1. 高可用方面
    在Kafka集群内部,所有的数据副本采用自动化的方式管理且会确保所有副本之间的数据是保持同步状态的。

当有Broker节点出现故障,需要重新选举leader, 那对应故障副本的分区均无法使用,选举完成后,需要做数据同步,分区越多, 服务不可用时间就会变长。

总而言之,合理的分区数量设置是非常重要的,保证kafka集群带来最高的吞吐量。在Kafka 集群中 Partition 总量过大或者单个 Broker 节点 Partition 过多,都可能会对系统的可用性和消息延迟带来潜在的负面影响,需要引起开发同学的重视。