《深入理解Kafka学习笔记:核心设计与实践原理》-第4章 主题与分区

第4章 主题与分区

从Kafka的底层实现来说,主题和分区都是逻辑上的概念,分区可以有一至多个副本,每个副本对应一个日志文件,每个日志文件对应一至多个日志分段(LogSegment),每个日志分段还可以细分为索引文件、日志存储文件和快照文件等。

4.1 主题的管理

4.1.1 创建主题

方式一:kafka-topics.sh
未指定副本分配参数replica-assignment,按照内部逻辑计算副本分配方案

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic test --partitions 10 --replication-factor 3

指定副本分配参数replica-assignment,直接按照副本分配参数创建主题

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic test --replica-assignment 2:0,0:1,1:2,2:1 

当topic名有“.” 时,会将"." 替换为“_” 例如:“topic.name_1” 会变成 “topic_name_1”
主题的命名同样不推荐(虽然可以这样做)使用双下画线“__”开头,因为以双下画线开头的主题一般看作Kafka的内部主题。

方式二:kafka.admin.TopicCommand 类
通过向 TopicCommand 类中传入一些关键参数,直接调用TopicCommand类中的main()函数来直接管理主题。

方式三:KafkaAdminClient

方式四:ZooKeeper
创建主题时,实质是在ZooKeeper的/brokers/topics下创建与该主题对应的子节点和配置信息。因此,直接使用 ZooKeeper 的客户端在/brokers/topics节点下创建相应的主题节点并写入预先设定好的分配方案,这样就可以创建一个新的主题了。

4.1.2 分区副本的分配

生产者分区分配: 为生产者确定消息发往哪个分区。
消费者分区分配: 为消费者确定前往哪个分区取消息。
创建主题分区分配: 为主题确定在哪些节点broker创建哪些分区副本。

  • 在创建主题时,如果使用了replica-assignment参数,那么就按照指定的方案来进行分区副本的创建;如果没有使用replica-assignment参数,那么就需要按照内部的逻辑来计算分配方案了。
  • 内部分配逻辑按照机架信息划分成两种策略:未指定机架信息和指定机架信息。如果集群中所有的 broker 节点都没有配置broker.rack参数,或者使用disable-rack-aware参数来创建主题,那么采用的就是未指定机架信息的分配策略,否则采用的就是指定机架信息的分配策略。

4.1.3 查看主题

有两种命令:list、describe
list查找所有可用topic

bin/kafka-topics.sh --zookeeper localhost:2181/kafka -list

describe查看主题信息,不加具体主题topic,则查看所有主题的详细信息

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --describe --topic test

4.1.4 修改主题

当一个主题被创建之后,依然允许我们对其做一定的修改,比如修改分区个数、修改配置等,这个修改的功能就是由kafka-topics.sh脚本中的alter指令提供的。
下面是增加分区的命令

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --alter --topic topic-config --partitions 3

上面这个命令会有告警信息,当主题中消息包含key时,根据key计算分区的行为会受到影响,原本发往分区0的消息会被发往分区1,2 对于基于key计算的主题而言,建议一开始设置好分区数量。

kafka只支持增加分区数而不支持减少分区数。
此功能完全可以实现,不过也会使代码的复杂度急剧增大。
考虑删除的分区中的消息如何处理,如果随着分区一起删除则消息的可靠性得不到保障,如果分散插入现有的分区,那么在消息量很大的时候,内部的数据复制会占用很大的资源,而且在复制期间,此主题的可用性又如何得到保障?如果直接存储到现有分区尾部,消息的时间戳就不会递增,如果分散插入现有的分区,内部的数据复制会占用很大的资源。与此同时,顺序性问题、事务性问题,以及分区和副本的状态机切换问题都是不得不面对的。
反观这个功能的收益点却是很低的,如果真的需要实现此类功能,则完全可以重新创建一个分区数较小的主题,然后将现有主题中的消息按照既定的逻辑复制过去即可。

4.1.5 配置主题

  • kafka-configs.sh 脚本是专门用来对配置进行操作的,这里的操作是指在运行状态下修改原有的配置,如此可以达到动态变更的目的。
  • kafka-configs.sh脚本包含变更配置alter和查看配置describe这两种指令类型。
  • 增、删、改的行为都可以看作变更操作
  • kafka-configs.sh脚本可以支持操作主题topics、brokers、用户users和客户端clients一共4种类型的配置。

kafka-configs.sh脚本使用entity-type参数来指定操作配置的类型,并且使用entity-name参数来指定操作配置的名称。
比如查看主题topic-config的配置可以按如下方式执行:

bin/kafka-config.sh --zookeeper localhost:2181/kafka --describe --entity-type topics --entity-name test

增加配置命令:

bin/kafka-config.sh --zookeeper localhost:2181/kafka --alter --entity-type topics --entity-name test --add-config cleanup.policy=compact,max.message.bytes=10000
  • 支持多个配置的操作,多个配置之间用逗号“,”
  • 用kafka-configs.sh脚本配置时,实质是在ZooKeeper中创建一个命名形式为/config/<entity-type>/<entity-name>的节点,并将变更的配置写入这个节点,节点内容中property-name代表属性名,property-value代表属性值。
  • 增加配置实际上是往节点内容中添加属性的键值对,修改配置是在节点内容中修改相应属性的属性值,删除配置是删除相应的属性键值对。
  • 变更配置时还会在ZooKeeper中的/config/changes/节点下创建一个以“config_change_”为前缀的持久顺序节点(PERSISTENT_SEQUENTIAL)

4.1.7 删除主题

方式一:kafka-topics.sh脚本
kafka-topics.sh脚本中的delete指令就可以用来删除主题,比如删除一个主题topic-delete:

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --delete test --if-exists
  • 必须将delete.topic.enable参数配置为true才能够删除主题,这个参数的默认值就是true,如果配置为false,那么删除主题的操作将会被忽略。
  • 如果要删除的主题是 Kafka 的内部主题,那么删除时就会报错。截至 Kafka 2.0.0,Kafka的内部一共包含2个主题,分别为__consumer_offsets和__transaction_state。
    方式二:zookeeper
  1. 在ZooKeeper中的/admin/delete_topics 路径下创建一个与待删除主题同名的节点,以此标记该主题为待删除的状态。
  2. 手动的方式来删除主题。主题中的元数据存储在 ZooKeeper 中的/brokers/topics 和/config/topics 路径下,主题中的消息数据存储在 log.dir 或log.dirs配置的路径下,我们只需要手动删除这些地方的内容即可。

4.2 初始化KafkaAdminClient

以程序调用API的方式对主题、broker、配置、ACL(Access Control List)管理。

4.2.1 基本使用

4.2.2 主题合法性验证

kafka-topics.sh脚本创建的方式一般由运维人员操作,普通用户无权过问。那么KafkaAdminClient就为普通用户提供了一个“口子”,或者将其集成到公司内部的资源申请、审核系统中会更加方便。
Kafka broker 端有一个这样的参数:create.topic.policy.class.name,默认值为null,它提供了一个入口用来验证主题创建的合法性。

4.3 分区的管理

4.3.1 优先副本的选举

优先副本: 一个分区副本集合的第一个副本称之为优先副本。比如主题 topic-partitions 中分区 0的AR集合列表(Replicas)为[1,2,0],那么分区0的优先副本即为1。
优先副本的选举: 通过一定的方式促使优先副本选举为leader副本,以此来促进集群的负载均衡,这一行为也可以称为“分区平衡”。

为什么要做优先副本的选举?
从某种程度上说,broker 节点中 leader 副本个数的多少决定了这个节点负载的高低。如果leader分布过于集中,就会造成集群负载不均衡。为了让系统负载均衡,我们总是需要让leader副本尽可能均匀地分布到 Kafka 集群的各个broker节点上。kafka系统broker节点会出现异常,lead副本会常常变换,解决方式是把优先副本作为leader副本,维护优先副本在Kafka集群中均匀分布,就是维护leader副本在各节点的均匀性。

优先副本的选举的局限性:
分区平衡并不意味着Kafka集群的负载均衡,有些leader副本的负载很高,比如需要承载TPS为30000的负荷,而有些leader副本只需承载个位数的负荷。也就是说,就算集群中的分区分配均衡、leader 分配均衡,也并不能确保整个集群的负载就是均衡的。

如何实现优先副本的选举?

  1. 自动平衡
    在 Kafka 中可以提供分区自动平衡的功能,与此对应的 broker 端参数是 auto.leader.rebalance.enable,此参数的默认值为true。在生产环境中不建议将设置为true,因为执行的时间无法自主掌控,这可能引起负面的性能问题,也有可能引起客户端一定时间的阻塞。
  2. 手动平衡(推荐)
    Kafka中kafka-perferred-replica-election.sh脚本提供了对分区leader副本进行重新平衡的功能,还提供了path-to-json-file参数来小批量地对部分分区执行优先副本的选举操作。

4.3.2 分区重分配

分区重分配的原因
集群上线或下线broker节点都会影响整个集群的负载均衡:

  1. 当集群中的一个节点突然宕机下线时,Kafka 并不会将该节点失效的分区副本自动地迁移到集群中剩余的可用broker节点上,如果放任不管,则不仅会影响整个集群的均衡负载,还会影响整体服务的可用性和可靠性。
  2. 当集群新增broker节点时,之前的主题分区并不会自动分配到新加入的节点中,因为在它们被创建时还没有这个新节点,这样新节点的负载和原先节点的负载之间严重不均衡。

分区重分配的操作
Kafka提供了Kafka-reassign-partitions.sh脚本来对分区进行迁移。它可以在集群扩容、broker节点失效的场景下分区进行迁移。
kafka-reassign-partitions .sh 脚本的使用分为3个步骤
①首先创建需要一个包含主题清单的JSON 文件
②其次根据主题清单和 broker 点清单生成一份重分配方案,

bin/kafka-reassign-partitions.sh --zookeeper localhost:2181/kafka --generate --topics-to-move-json-file reassign.json --broker-list 0,2

③最后根据这份方案执行具体的重分配动作。

bin/kafka-reassign-partitions.sh --zookeeper localhost:2181/kafka --execute --reassignment-json-file project.json

分区重分配的原理:
先通过控制器为每个分区添加新副本(增加副本因子),新的副本将从分区的leader副本那里复制所有的数据。根据分区的大小不同,复制过程可能需要花一些时间,因为数据是通过网络复制到新副本上的。在复制完成之后,控制器将旧副本从副本清单里移除(恢复为原先的副本因子数)。注意在重分配的过程中要确保有足够的空间。

4.4如何选择合适的分区

4.4.1 性能测试工具

在Kafka中,性能与分区数有着必然的关系,在设定分区数时一般也需要考虑性能的因素。对不同的硬件而言,其对应的性能也会不太一样。在实际生产环境中,我们需要了解一套硬件所对应的性能指标之后才能分配其合适的应用和负荷,所以性能测试工具必不可少。

本节要讨论的性能测试工具是 Kafka 本身提供的用于生产者性能测试的 kafka-producer-perf-test.sh和用于消费者性能测试的kafka-consumer-perf-test.sh。

4.4.2 分区数越多吞吐量就越高吗

分区是Kafka 中最小的并行操作单元,对生产者而言,每一个分区的数据写入是完全可以并行化的;对消费者而言,Kafka 只允许单个分区中的消息被一个消费者线程消费,一个消费组的消费并行度完全依赖于所消费的分区数。

具体吞吐量的数值和走势还会和磁盘、文件系统、I/O调度策略相关。

4.4.3 分区数的上限

执行完成后可以检查 Kafka 的进程是否还存在(比如通过 jps 命令或 ps-aux|grep kafka命令)。

4.4.4 考量因素

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

当生产者向Kafka中写入基于key的消息时,Kafka通过消息的key来计算出消息将要写入哪个具体的分区,这样具有相同 key 的数据可以写入同一个分区。

再比如对于同一个key 的所有消息,消费者需要按消息的顺序进行有序的消费,如果分区的数量发生变化,那么有序性就得不到保证。在创建主题时,最好能确定好分区数,这样也可以省去后期增加分区所带来的多余操作。尤其对于与key高关联的应用,在创建主题时可以适当地多创建一些分区,以满足未来的需求。

分区数的多少还会影响系统的可用性
如果集群中的某个broker节点宕机,那么就会有大量的分区需要同时进行leader角色切换,这个切换的过程会耗费一笔可观的时间,并且在这个时间窗口内这些分区也会变得不可用。

分区数越多也会让Kafka的正常启动和关闭的耗时变得越长,与此同时,主题的分区数越多不仅会增加日志清理的耗时,而且在被删除时也会耗费更多的时间。

4.5 总结

本章主要讲述了Kafka概念中的两大核心—主题和分区。通过对主题的增删查改、配置管理等内容来了解主题相关的知识点。通过对分区副本的一系列操作及分区数设定的考量因素来理解分区相关的概念,比如优先副本、限流、分区重分配等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《深入理解kafka核心设计实践原理》是一本介绍Kafka的书籍,主要涵盖了Kafka核心设计实践原理Kafka是一个分布式的消息队列系统,被广泛应用于大数据领域。本书从Kafka的基本概念入手,详细介绍了Kafka的架构、消息存储、消息传输、消息消费等方面的内容。同时,本书还介绍了Kafka的高级特性,如事务、流处理、安全等方面的内容。对于想要深入了解Kafka的读者来说,这本书是一本不可多得的好书。 ### 回答2: ### 回答3: Kafka是一个高性能的分布式消息系统,可以承载海量数据流,支持高可靠、高吞吐量的消息传递。它具有良好的扩展性、稳定性和可管理性,在现代数据架构中占据了非常重要的地位。本文将深入探讨Kafka核心设计实践原理,让读者更全面地了解这个流行的消息系统。 1. 消息模型 Kafka的消息模型以消息为中心,将数据分为多个Topic,每个Topic可以有多个Partition。Producer将消息发送到指定的Topic,Consumer可以订阅特定的Topic并接收其中的消息。在每个Partition中,Kafka将消息以offset为单位进行存储,保证数据的可靠性和顺序性。 2. 存储机制 Kafka使用分布式的文件存储机制,将消息以Segment为单位进行存储。每个Segment包含一个或多个消息,使用mmap技术将数据加载到内存中,提高读写速度。Kafka还支持消息的压缩和索引优化,使得数据的存储更加高效。 3. 管理机制 Kafka的管理机制由Controller、Broker、Zookeeper三个组件构成。Controller负责管理整个Kafka集群的状态和各个Broker之间的主从关系,Broker则负责存储消息和处理数据。而Zookeeper则提供了集群的元数据管理和Leader选举功能。 4. 性能优化 Kafka通过异步IO和Zero-copy等技术提高数据的读写性能,同时支持消息的批量处理和预取机制,减少磁盘操作和网络开销。此外,Kafka还支持动态分区分区再平衡等高可用性机制,确保数据的可靠性和可用性。 总之,深入理解Kafka核心设计实践原理,可以帮助用户更好地应用这一消息系统,提升系统的可靠性和性能。同时,了解Kafka原理也有助于用户更好地进行系统的调优和排错,提高系统的稳定性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值