Apache Flink - 将流平均划分为输入 Kafka 主题

Apache Flink - Partitioning the stream equally as the input Kafka topic

我想在 Apache Flink 中实现以下场景:

给定一个有 4 个分区的 Kafka 主题,我想在 Flink 中根据事件的类型使用不同的逻辑独立处理分区内数据。

特别地,假设输入的 Kafka 主题包含前面图像中描述的事件。每个事件都有不同的结构:分区 1 的字段“a”作为键,分区 2 的字段“b”作为键,等等. 在 Flink 中,我想根据事件应用不同的业务逻辑,所以我认为我应该以某种方式拆分流。为了实现图片中描述的效果,我想只使用一个消费者来做类似的事情(我不明白为什么我应该使用更多):

FlinkKafkaConsumer<..> consumer = ...
DataStream<..> stream = flinkEnv.addSource(consumer);

stream.keyBy("a").map(new AEventMapper()).addSink(...);
stream.keyBy("b").map(new BEventMapper()).addSink(...);
stream.keyBy("c").map(new CEventMapper()).addSink(...);
stream.keyBy("d").map(new DEventMapper()).addSink(...);

(a) 是否正确? 此外,如果我想并行处理每个 Flink 分区,因为我只对按顺序处理已排序的事件感兴趣通过相同的 Kafka 分区,而不是全局考虑它们,(b) 我该怎么做?我知道这个方法的存在setParallelism(),但我不知道在这种情况下该用在什么地方。

我正在寻找有关标记为 (a)(b) 的问题的答案。提前谢谢你。

如果你能像这样构建它,它的性能会更好:

具体来说,我的建议是

  1. 将整个作业的并行度设置为与Kafka分区数完全匹配。然后每个 FlinkKafkaConsumer 个实例将从恰好一个分区读取。

  2. 如果可能,避免使用keyBy,并避免改变并行度。然后 source、map 和 sink 都将链接在一起(这称为 operator chaining),并且不需要 serialization/deserialization 也不需要网络(在 Flink 中)。这不仅会表现良好,而且您还可以利用 fine-grained 恢复(令人尴尬的并行流作业可以恢复一个失败的任务而不会中断其他任务)。

  3. 您可以编写一个通用的 EventMapper 来检查正在处理的事件类型,然后执行任何适当的操作。或者您可以尝试变得聪明并实现一个 RichMapFunction,在其 open() 中确定正在处理哪个分区,并加载适当的映射器。