Flink keyBy 与 RichParallelSourceFunction

Flink keyBy vs 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 时,流记录都必须经过 serialization/deserialization,并且很可能会通过网络发送。另一方面,源实例可以 链接 到后续操作,这意味着流记录只是作为 java 堆上的对象传递。

当您有 Kafka 或 Kinesis 之类的多个源实例时,它们不会划分流。每个实例独立地连接到相关的 brokers/servers 来处理它们被分配处理的 partitions/shards 的记录。因此,使用 RichParallelSourceFunction,您有可能以更少的 serialization/deserialization 和网络开销实现性能更高的管道。

(2) 为什么所有内容都转到子任务 3?

你的 KeySelector 函数的结果被散列,这些散列值被取 mod 128(假设你没有重新配置密钥组的数量)将每个密钥映射到 关键组。然后 Flink 确定哪个子任务负责这些关键组。

鉴于您的关键函数只能 return 两个不同的值(0 和 1),您只会看到一个或两个不同的子任务在使用中。显然 0 和 1 都散列到已分配给子任务 3 的密钥组。

只要有可能,最好有一个键 space 明显大于集群的并行度。

参考资料

要了解更多信息,请参阅我对这些问题的回答: