Kafka 主题和分区

135 阅读7分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

主题和分区是Kafka 的两个核心概念,主题作为消息的归类,可以再细分为一个或多个分区,分区也可以看作对消息的二次归类。分区的划分不仅为Kafka提供了可伸缩性、水平扩展的功能,还通过多副本机制来为Kafka提供数据冗余以提高数据可靠性。

从Kafka的底层实现来说,主题和分区都是逻辑上的概念,分区可以有一至多个副本,每个副本对应一个日志文件,每个日志文件对应一至多个日志分段(LogSegment),每个日志分段还可以细分为索引文件、日志存储文件和快照文件等。不过对于使用Kafka进行消息收发的普通用户而言,了解到分区这一层面足以应对大部分的使用场景。

主题的管理

主题的管理包括创建主题、查看主题信息、修改主题和删除主题等操作。可以通过 Kafka提供的 kafka-topics.sh 脚本来执行这些操作,这个脚本位于$KAFKA_HOME/bin/目录下。

主题的管理并非只有使用 kafka-topics.sh 脚本这一种方式,我们还可以通过KafkaAdminClient 的方式实现(这种方式实质上是通过发送 CreateTopicsRequest、DeleteTopicsRequest 等请求来实现的),甚至我们还可以通过直接操纵日志文件和ZooKeeper节点来实现。

分区的管理

分区的管理包括优先副本的选举、分区重分配、复制限流、修改副本因子等。

分区数的选择

如何选择合适的分区数?一个“恰如其分”的答案就是视具体情况而定。

从吞吐量方面考虑,增加合适的分区数可以在一定程度上提升整体吞吐量,但超过对应的阈值之后吞吐量不升反降。如果应用对吞吐量有一定程度上的要求,则建议在投入生产环境之前对同款硬件资源做一个完备的吞吐量相关的测试,以找到合适的分区数阈值区间。

在创建主题之后,虽然我们还能够增加分区的个数,但基于key计算的主题需要严谨对待。当生产者向Kafka中写入基于key的消息时,Kafka通过消息的key来计算出消息将要写入哪个具体的分区,这样具有相同 key 的数据可以写入同一个分区。Kafka 的这一功能对于一部分应用是极为重要的,比如日志压缩(Log Compaction);再比如对于同一个key 的所有消息,消费者需要按消息的顺序进行有序的消费,如果分区的数量发生变化,那么有序性就得不到保证。在创建主题时,最好能确定好分区数,这样也可以省去后期增加分区所带来的多余操作。尤其对于与key高关联的应用,在创建主题时可以适当地多创建一些分区,以满足未来的需求。通常情况下,可以根据未来2年内的目标吞吐量来设定分区数。当然如果应用与key弱关联,并且具备便捷的增加分区数的操作接口,那么也可以不用考虑那么长远的目标。

有些应用场景会要求主题中的消息都能保证顺序性,这种情况下在创建主题时可以设定分区数为1,通过分区有序性的这一特性来达到主题有序性的目的。

当然分区数也不能一味地增加,分区数会占用文件描述符,而一个进程所能支配的文件描述符是有限的,这也是通常所说的文件句柄的开销。虽然我们可以通过修改配置来增加可用文件描述符的个数,但凡事总有一个上限,在选择合适的分区数之前,最好再考量一下当前Kafka进程中已经使用的文件描述符的个数。

分区数的多少还会影响系统的可用性。Kafka通过多副本机制来实现集群的高可用和高可靠,每个分区都会有一至多个副本,每个副本分别存在于不同的broker节点上,并且只有leader副本对外提供服务。在Kafka集群的内部,所有的副本都采用自动化的方式进行管理,并确保所有副本中的数据都能保持一定程度上的同步。当broker发生故障时,leader副本所属宿主的broker节点上的所有分区将暂时处于不可用的状态,此时Kafka会自动在其他的 follower 副本中选举出新的 leader 用于接收外部客户端的请求,整个过程由Kafka控制器负责完成(有关控制器的内容可以参考6.4节)。分区在进行leader角色切换的过程中会变得不可用,不过对于单个分区来说这个过程非常短暂,对用户而言可以忽略不计。如果集群中的某个broker节点宕机,那么就会有大量的分区需要同时进行leader角色切换,这个切换的过程会耗费一笔可观的时间,并且在这个时间窗口内这些分区也会变得不可用。

分区数越多也会让Kafka的正常启动和关闭的耗时变得越长,与此同时,主题的分区数越多不仅会增加日志清理的耗时,而且在被删除时也会耗费更多的时间。对旧版的生产者和消费者客户端而言,分区数越多,也会增加它们的开销,不过这一点在新版的生产者和消费者客户端中有效地得到了抑制。

如何选择合适的分区数?从某种意思来说,考验的是决策者的实战经验,更透彻地说,是对Kafka本身、业务应用、硬件资源、环境配置等多方面的考量而做出的选择。在设定完分区数,或者更确切地说是创建主题之后,还要对其追踪、监控、调优以求更好地利用它。读者看到本节的内容之前或许没有对分区数有太大的困扰,而看完本节的内容之后反而困惑了起来,其实大可不必太过惊慌,一般情况下,根据预估的吞吐量及是否与key相关的规则来设定分区数即可,后期可以通过增加分区数、增加broker或分区重分配等手段来进行改进。如果一定要给一个准则,则建议将分区数设定为集群中broker的倍数,即假定集群中有3个broker节点,可以设定分区数为3、6、9等,至于倍数的选定可以参考预估的吞吐量。不过,如果集群中的broker 节点数有很多,比如大几十或上百、上千,那么这种准则也不太适用,在选定分区数时进一步可以引入基架等参考因素。

参考

  • 深入理解Kafka:核心设计与实践原理 2019 朱忠华 此材料可能受版权保护。

如果这篇文章帮助到了你,欢迎评论、点赞、转发。