Apache Flink,逻辑或物理运算符中的Keyby数据分布?

Posted

技术标签:

【中文标题】Apache Flink,逻辑或物理运算符中的Keyby数据分布?【英文标题】:Keyby data distribution in Apache Flink, Logical or Physical Operator? 【发布时间】:2020-10-05 07:28:33 【问题描述】:

根据 Apache Flink 文档,KeyBy 转换在逻辑上将流划分为不相交的分区。具有相同键的所有记录都分配到同一个分区。

KeyBy 是 100% 逻辑转换吗?它不包括跨集群节点分布的物理数据分区吗?如果是这样,那么如何保证所有具有相同key的记录都分配到同一个分区?

例如,假设我们从 n 个节点的 Apache Kafka 集群获取分布式数据流。运行我们的流式作业的 Apache Flink 集群由 m 个节点组成。当 keyBy 转换应用于传入的数据流时,它如何保证逻辑数据分区?还是涉及跨集群节点的物理数据分区?

我似乎对逻辑数据分区和物理数据分区感到困惑。

【问题讨论】:

【参考方案1】:

所有可能键的键空间被划分为一些键组。 key group 的数量(与最大并行度相同)是你在搭建 Flink 集群时可以设置的配置参数;默认值为 128。

每个键都属于一个键组。当集群启动时,键组在任务管理器之间划分——如果集群从检查点或保存点启动,这些快照按键组索引,每个任务管理器加载键中键的状态已分配的组。

在作业运行时,每个任务管理器都知道用于计算键的键选择器函数,以及键如何映射到键组。 TM 还知道密钥组到任务管理器的分区。这使得将每条消息路由到负责该消息密钥的任务管理器变得简单。

详情:

密钥所属的密钥组大致如下计算:

Object key = the result of your KeySelector function;
int keyHash = key.hashCode();
int keyGroupId = MathUtils.murmurHash(keyHash) % maxParallelism;

给定键组中的元素应路由到给定实际并行度的运算符实例的索引,maxParallelism 计算为

keyGroupId * parallelism / maxParallelism

实际代码在org.apache.flink.runtime.state.KeyGroupRangeAssignment,如果你想看的话。

一个主要的结论是键组是不相交的,它们跨越键空间。换句话说,不可能出现不属于其中一个密钥组的密钥。每个密钥恰好属于一个密钥组,每个密钥组都属于一个 的任务管理器。

【讨论】:

在将消息路由到 TM 时,一些 TM 可能驻留在其他物理计算节点上。在这种情况下,需要将消息发送到另一个节点。对?这不是数据的物理移动,或者换句话说,物理数据分区吗? 是的,没错。 keyBy 的逻辑分区可能涉及物理分区,也可能不涉及物理分区。 意思是“……可能,也可能不……”。 @DavidAnderson 我有点困惑。启动集群时,任务管理器如何知道密钥是什么以便分配密钥组?此外,当流中出现不属于任何密钥组的新密钥时,是否会创建新密钥组并将其分配给其中一个 TM? @HarshithBolar 我已经用更多细节扩展了我的答案。希望这能消除混乱。

以上是关于Apache Flink,逻辑或物理运算符中的Keyby数据分布?的主要内容,如果未能解决你的问题,请参考以下文章

Showplan 逻辑运算符和物理运算符参考

Flink-transformation

Flink中逻辑计划和物理计划的概念划分和对应关系

Apache flink:使用keyBy / connect维护流中的消息输入顺序

排序后的Flink join运算符似乎是组字段(Scala)

flink流计算随笔