Apache Flink 中的 Keyby 数据分布,逻辑算子还是物理算子?

Keyby data distribution in Apache Flink, Logical or Physical Operator?

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

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

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

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

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

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

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

详情:

一个key所属的key组大致是这样计算的:

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中,如果你想看的话

一个重要的收获是键组是不相交的,并且它们跨越键空间。换句话说,不属于其中一个密钥组的密钥不可能出现。每个键都属于一个键组,每个键组都属于一个 任务管理器。