【问题标题】:Kafka Streams: Stream Thread vs Partition of multiple topicsKafka Streams:流线程与多个主题的分区
【发布时间】:2019-10-28 07:46:44
【问题描述】:

假设我有 2 个主题,比如 xyz1、xyz2,每个主题有 3 个分区。如果我有一个具有 3 个线程的 Kafka 流应用程序,是否会出现以下情况?

Thread                  Partition
    1       xyz1-partition 0, xyz2-partition 2
    2       xyz1-partition 1, xyz2-partition 0
    3       xyz1-partition 2, xyz2-partition 1

相对于:

Thread                  Partition
    1       xyz1-partition 0, xyz2-partition 0
    2       xyz1-partition 1, xyz2-partition 1
    3       xyz1-partition 2, xyz2-partition 2

本质上,单个线程消耗来自 2 个不同主题的特定分区的数据,并且分区号可能会有所不同?假设我们使用低级处理器 API

【问题讨论】:

    标签: apache-kafka apache-kafka-streams


    【解决方案1】:

    这种情况是否会发生取决于您的拓扑。

    实际上,流任务分配给流线程,而不是普通分区。每个任务可以处理一组分区。一组包含一个或多个分区。如果组包含多个分区,则它始终包含不同主题的相同分区(即具有相同分区号的分区)。例如,一个组可能包含 xyz1-partition 0、xyz2-partition 0 但不包含 xyz1-partition 0、xyz2-partition 2。这假设不同的主题使用相同的分区策略。需要对不同主题的相同分区进行这种共同分区 - 例如 - 在连接的情况下,具有相同键的记录必须由相同的流任务处理,类似于您的第二种情况。

    如果您假设在第一个示例中每个分区都由不同的流任务处理,即每个分区组包含一个分区,则可能会发生这种情况。

    如果假设每一行的两个partition都由同一个stream task处理(即两个partition属于同一个partition group),这种情况就不会发生,因为partition group不能包含不同的partition。

    有关分配策略的更多信息,请参阅https://github.com/apache/kafka/blob/e4262471c9aee4a4c04dd04ebbdbdba7e3c5ead1/streams/src/main/java/org/apache/kafka/streams/processor/internals/StreamsPartitionAssignor.java#L297

    也就是说,其实有一种方法可以通过实现PartitionGrouper接口将不同的分区分配给同一个任务。但是,此接口将在 2.4 中弃用并在 3.0 中删除。见https://cwiki.apache.org/confluence/display/KAFKA/KIP-528%3A+Deprecate+PartitionGrouper+configuration+and+interface

    【讨论】:

      【解决方案2】:

      视情况而定

      普通的 Kafka 消费者:

      Kafka Consumer Group 由具有相同 group.id 的消费者/实例/进程池组成。id 可以在同一台机器上运行,也可以在分布式机器上运行。 Kafka Consumer使用rebalancing为每个consumer分配partition而不重叠意味着一个partition最多可以分配Consumer Group的一个consumer进程。

      消费者也可以使用assign(Collection)手动分配特定的分区(类似于旧的“简单”消费者)。在这种情况下,动态分区分配和消费者组协调将被禁用

      因此在重新平衡时可以将分区分配给任何线程。

      Kafka 流:

      Kafka 使用流任务作为逻辑单元来分配分区和并行化进程。 Kafka Stream 基于流分区创建多个流任务,并为每个任务分配一个分区列表。 一旦将任务分配给分区,它将坚持并管理它们自己的拓扑上的并行性。因此,流任务可以独立并行处理,无需人工干预。

      分组的 PartitionGrouper 接口的默认实现 按分区 id 进行分区。加入操作需要主题 的加入实体被划分,即,被划分为 相同的键和具有相同数量的分区。共分 通过在连接主题上具有相同数量的分区来确保, 并通过使用序列化和 Producer 的默认分区器。here

      因此,在您的情况下,场景 1 不可能,而场景 2 是可能的。

      【讨论】:

      • 这仅适用于普通KafkaConsumers -- Kafka Streams 使用了无法覆盖的自定义PartitionAssignor,并根据执行的Topology 的结构应用特殊逻辑。
      • Kafka Streams 中的Task,不会获得默认分配不同编号的分区(可以使用自定义PartitionGrouper 更改默认行为,但此接口将在 2.4 版本中弃用将在 3.0 中删除:cwiki.apache.org/confluence/display/KAFKA/…)。因此,默认情况下(1)是不可能的。
      猜你喜欢
      • 2018-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 2016-10-15
      相关资源
      最近更新 更多