Kafka 消息队列中主题和分区

2020-05-20 0 By admin

主题和分区是 Kafka 的两个核心概念。
主题作为消息的归类,下面可以在细分一个或多个分区,为消息提供了二次分类。分区的划分提高了消息的可扩展性和伸缩性,还可以通过多副本机制为kafka做数据冗余以提高数据可靠性。
对kafka底层来说,主题和分区只是逻辑上的概念,分区可以有一至多个副本,每个副本对应一个日志,每个日志对应有一至多个日志分段每个日志分段还可以细分为索引文件、日志存储文件和快照文件等。不过对于使用 Kafka 进行消息收发的普通用户而言,了解到分区这一层面足以应对大部分的使用场景。

一、主题的管理

主题的管理包括创建主题、删除主题、查看和修改主题等。可以通过kafka提供的 kafka-topics.sh 脚本来执行操作。这个脚本位于$KAFKA_HOME/bin/目录下,其核心代码仅有一行,具体如下:
exec $(dirname $0)/kafka-run-class.sh kafka.admin.TopicCommand "$@"
可以看到 这行实质上是调用了 kafka.admin.topicCommand 来实现的。
kafka主题的管理还可以通过 kafkaAdminClient 来实现,这种方式本质上是通过 CreateTopicsRequest、DeleteTopicsRequest等命令来实现。
甚至我们还可以通过日志文件和zookeeper脚本来实现。下面按照创建、查看、修改和删除主题的顺序来看操作细节。

1.1、自动创建主题

如果 broker 端配置参数 auto.create.topics.enable 设置为true(默认),那么当生产者向一个未创建的主题发送消息时,会自动创建一个分区数为 num.partitions (默认为1)、副本为 default.replication.factor(默认为1)的主题。
除此之外,当一个消费者开始向未知主题中读取消息时,或者当任意一个客户端向未知主题发送元数据请求时,都会按照配置参数 num.partitions和default.replication.factor 的值来创建一个相应的主题。
很多时候,这种自动创建主题的行为都是非预期的。除非有特殊应用需求,否则不建议将 auto.create.topics.enable 参数设置为 true,这个参数会增加主题的管理与维护的难度。

1.2、手动创建主题

更加推荐和通用的方法是通过 kafka-topics.sh 脚本来创建主题。
# bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic topic-create --partitions 4 --replication-factor 2
创建了一个分区为4,副本为2,名称为 topic-create 的主题。
执行完脚本之后,Kafka 会在 log.dir 或 log.dirs 参数所配置的目录下创建相应的主题分区,默认情况下这个目录为 /tmp/kafka-logs/。
不仅可以通过日志文件的根目录来查看集群中各个 broker 的分区副本的分配情况,还可以通过 Zookeeper 客户端来获取。
当创建一个主题时会在 Zookeeper 的 /brokers/topics/ 目录下创建一个同名的实节点,改节点中记录了该主题的分区副本分配方案。

1.3、分区副本的分配

在生产者和消费者中也有分区分配的概念,生产者分配分区是为每条消息指定要发往的分区,消费者分配分区是为消费者指定可以消费那些分区中的消息。而这节的分区分配是指为集群制定创建主题时的分区副本分配方案,也就是在那个 broker 中从创建那些分区的副本。
在创建主题时,如果使用了 replica-assignment 参数,那么就按照指定的方案来进行分区副本的创建;如果没有使用 replica-assignment 参数,那么就需要按照内部的逻辑来计算分配方案。

1.4、配置管理

kafka-configs.sh 脚本是专门用来对配置进行操作的,这里的操作是指在运行状态下修改原有的配置,如此可以达到动态变更的目的。kafka-configs.sh 脚本包含变更配置 alter 和查看配置 describe 这两种指令类型。

1.5、初识KafkaAdminClient

一般情况下,我们习惯使用 kafka-topics.sh 脚本来管理主题。但有些时候我们希望将主题管理类的功能集成到公司内部系统中,集管理、监控、运维、警告等一体,那么就需要以程序调用API的方式去实现。这节主要记录 KafkaAdminClient 的基本使用方式,以及采用这种方式创建主题时的合法性验证。