如何为Kafka集群选择合适的Topic/Partitions数量

时间:2022-09-05 08:06:32
介绍一些与本问题相关的一些重要决策因素,并提供一些简单的计算公式
越多的分区可以提供更高的的吞吐
首先要明白,在kafka中,单个partition是kafka并行操作的最小单元,在producter和broker端,向每一个分区写入数据是完全可以并行的,此时,可以通过加大硬件资源的利用率来提升系统的吞吐量,例如对数据进行压缩,在consumer端, kafka只允许单个partition的数据被一个consumer线程消费,因此,在consumer端,每个consumer group内部的consumer并行度完全依赖与被消费的分区数量。综上,通常情况下,在一个kafka集群中,partition的数量越多,意味这可以到达的吞吐量越大。
分区数量的计算:
我们可以粗略的通过吞吐量来计算kafka集群的分区数量,假设对于单个partition,producer端可达吞吐量为p,consumer端可达吞吐量为c,期望的目标吞吐量为t,那么集群所需要的partition数量至少为max(t/p,t/c),在producter端,单个分区的吞吐量大小会收到批量大小,数据压缩方法,确认类型(同步异步),复制因子等配置参数的影响,经过测试,在producer端,单个partition的吞吐量通常在10MB/s左右,在consumer端,单个partition的吞吐依赖于consumer端每个消息的应用逻辑处理速度。
随着时间的推移,我们能够对分区的数量进行添加,但是对于基于key的hash来分区的topic,我们最好根据未来1到2年的目标吞吐量来设计kafka的分区数量。
越多的分区需要打开更多的本地文件句柄
在kafka的broker中,每个分区都会对照着文件系统的一个目录,在kafka的数据日志文件目录中,每个日志数据段都会分配两个文件,一个索引文件和一个数据文件,每个broker会为每个日志段文件打开一个index文件和一个数据文件句柄,因此,随着partition的增多,需要底层操作系统配置更高的文件句柄数量限制。这更多的是一个配置问题。
更多的分区会导致更高的不可用性
kafka通过多副本复制技术,实现kafka集群的高可用和稳定性,每个partition都会有多个数据副本,每个副本分别存在于不同的broker,所有的数据副本中,有一个数据副本为leader,其他的数据副本为follower,在kafka集群内部,所有的数据副本皆采用自动化的方式进行管理,并且确保所有的数据副本的数量皆保持同步状态,不论是producer端还是consumer端发往partition的请求,皆通过leader数据副本所在broker来处理,当broker发生故障时,对于leader数据副本在该broker的所有partition将暂时不可用,kafka将会自动在其他的数据副本中选择一个leader,用于接受客户端的请求 ,这个过程由kafka 的 controller节点的broker自动完成。主要是从zk读取和修改受影响partition的一些元信息。对zookeeper的所有操作都是由kafka controller来完成的
通常情况下, 当一个broker有计划的停止服务时,那么controller会在服务停止之前,将该broker上的所有leader一个一个的移走,由于单个leader的移动时间大约只需要几毫秒,因此从客户层面看,有计划的服务停机只会导致系统在很小时间窗口中不可用
然后,当broker非计划的停止服务时,例如kill -9  ,系统的不可用时间窗口将会与受影响的partition数量有关。假如,一个2节点的kafka集群中存在2000个partition,每个partition有2个数据副本。当其中一个broker非计划的宕机后,所有1000个partition同时变的不可用。假设每个partition有5毫秒的时间恢复,1000个就要5秒的恢复时间,
如果更不幸的是宕机的broker是controller节点时,在这种情况下,新leader节点的选举在controller节点恢复之前是不会启动的,controller节点的错误恢复将会自动进行,但是新的controller节点需要从zookeeper中读取每个partition的元信息用户初始化数据。加入从zk读取一个partition要用2ms,有10000个partition的话,则controller的恢复将会增加约20s
所以最好将每个broker的partition的数据限制在2000到4000,每个kafka集群中partition的数量限制在10000以内。
越多的分区可能增加端对端的延迟
kafka端对端延迟定义为producer端发布消息到consumer端接收消息所需要的时间。即consumer接收消息的时间减去producer发布消息的时间。kafka只有在消息提交之后,才会将消息暴露给消费者。例如消息在所有in-sync副本列表同步复制完成后才会暴露。因此in-sync副本复制所花的时间是kafka端对端延迟的主要部分。在默认情况下,每个broker从其他broker节点进行数据副本复制时,该broker节点只会为此工作分配一个线程,该线程需要完成该broker所有partition数据复制。将1000个partition从一个broker复制到另一个broker所带来的时间延迟约为20ms,这意味着端对端的延迟至少是20ms,这样的延迟对一些实时应用需求来说显得过长。要么可以通过加大kafka集群来缓解。将1000个分区leader放到1个broker和放到10个broker,他们之间的延迟是存在差异的。10个broker节点的集群中,每个broker节点平均需要处理100个分区的数据复制,延迟将下降。
如果十分在意消息延迟的问题,限制每个broker节点的partition数量是一个很好的主意:对于b个broker节点和复制因子为r的kafka集群。整个kafka集群的partition数量最好不超过100 * b * r
总结; kafka集群中越多的partition会带来越高的吞吐量,但是我们必须意识到集群的partition总量多大或者单个broker节点partition过多,都会对系统的可用性和消息延迟带来潜在的影响。