Flink keyBy与RichParallelSourceFunction

问题描述

我正在学习flink,并试图理解一些概念。这里有几个问题:

  1. 在流上进行keyBy操作和从RichParallelSourceFunction子对象(例如FlinkKinesisConsumer获取源有什么区别?这两个操作都会分割流。
  2. 还尝试实现一个非常简单的keyBy运算符来理解它,如下所示: DataStream input = env.fromElements("1","2","3","4","5","6") .keyBy((KeySelector<String,Integer>) value -> Integer.parseInt(value) % 2); DataStream parsed = input.map(new MyMapper()); DataStream parsedStr = input.map(new MyStrMapper()); parsed.print(); parsedStr.print(); env.execute("myParser");

但是我得到的输出令人困惑:

3> 1
3> 2
3> 3
3> 4
3> 5
3> 6
3> I am 1
3> I am 2
3> I am 3
3> I am 4
3> I am 5
3> I am 6

这意味着在子任务3上执行的所有操作。有人可以帮助解释原因吗?

解决方法

(1)使用keyBy与使用RichParallelSourceFunction之间的区别?

每次使用keyBy时,流记录必须经过序列化/反序列化,并且可能会通过网络发送。另一方面,可以将源实例链接到后续操作,这意味着流记录只是作为对象传递到java堆上。

当您具有Kafka或Kinesis之类的多个源实例时,它们不会划分流。每个实例都独立地连接到相关的代理/服务器,以处理已分配给它们处理的分区/碎片的记录。因此,使用RichParallelSourceFunction,您可以实现性能更高的管道,而序列化/反序列化和联网所需的开销更少。

(2)为什么所有内容都将进入子任务3?

KeySelector函数的结果进行哈希处理,并将这些哈希值取为mod 128(假设您尚未重新配置密钥组的数量),以将每个密钥映射到密钥组。然后Flink确定哪个子任务负责这些关键组。

鉴于您的键函数只能返回两个不同的值(0和1),因此您只会看到一个或两个不同的子任务正在使用。显然0和1都哈希到已分配给子任务3的键组。

只要有可能,最好有一个比集群的并行性大得多的密钥空间。

参考

有关更多信息,请参阅我对以下问题的回答: