Join ApacheFlink:两个(或多个)任务管理器之间的共享状态

Join ApacheFlink:两个(或多个)任务管理器之间的共享状态,join,state,apache-flink,Join,State,Apache Flink,假设我有两个任务管理器,每个任务管理器只有一个任务槽。现在,我有以下工作: KeyedStream streamA=env.addSource(…).keyBy(…); KeyedStream streamB=env.addSource(…).keyBy(…); streamA.connect(streamB.flatMap(newstatefuljoinfunction()).setParallelism(2); 一个任务管理器将使用来自卡夫卡主题的数据,另一个任务管理器将使用来自另一个卡夫

假设我有两个任务管理器,每个任务管理器只有一个任务槽。现在,我有以下工作:

KeyedStream streamA=env.addSource(…).keyBy(…);
KeyedStream streamB=env.addSource(…).keyBy(…);
streamA.connect(streamB.flatMap(newstatefuljoinfunction()).setParallelism(2);
一个任务管理器将使用来自卡夫卡主题的数据,另一个任务管理器将使用来自另一个卡夫卡主题的数据

我将作业发送给作业管理器以执行它。Flink分配两个任务管理器来处理flatMap(因为任务管理器只有一个任务槽)

flatMap在事件之间进行简单连接(使用两个键控状态):

public class StatefulJoinFunction扩展了Flink博客上的RichCoFlatMapFunction,似乎两个任务管理器可以通过TCP连接进行通信,这对我来说很有意义,因为在某些情况下我们需要在事件之间共享状态。如果这是错误的,您能向我解释一下Flink是如何处理以下情况的吗?


假设始终有两个任务管理器,物理上位于两个集群节点上。每个任务管理器始终只有一个插槽。我运行上述作业并将并行度设置为2(例如,在将作业发送到作业管理器时使用-p参数)。现在,Flink将从我的工作中创建两个结构相同的子任务,并将它们发送给任务管理器。两个任务管理器都将执行“相同”的作业,但使用不同的事件。作业使用两个Kafka主题中的事件:A和B。这意味着第一个和第二个任务管理器将同时使用主题A和B中的事件,但使用不同的事件,否则会有重复的事件。作业是相同的,即它执行上述RichCoFlatMapFunction,然后每个任务管理器将在本地处理其已使用的事件集和个人本地状态。现在问题来了:假设第一个任务管理器使用了一个键为“1”的事件。此事件到达RichCoFlatMapFunction内部,并存储在状态中,因为操作员仍在等待另一个具有相同键的事件来生成联接。如果第二个任务管理器使用了另一个键为“1”的事件,并且它们不共享状态或通信,则无法加入我的推理有什么错?

两个任务管理器不需要为了状态共享而进行通信——Flink中没有状态共享

下面显示的这三个执行图中的任何一个都是可能的,这取决于您如何安排源的细节。在每个图的左边,我们看到A和B的源操作符,在右边,两个平行的双输入操作符实例通过RichCoFlatMap实现连接

keyBy不是运算符,而是指定源和两个RichCoFlatMap实例的连接方式。它将其安排为哈希连接,对源流进行重新分区

使用这三种场景中的哪一种并不重要,因为在所有三种情况下,keyBy将具有相同的效果,即引导某些键的所有事件到Join1,以及引导其他键的所有事件到Join2

换句话说,对于任何给定的键,该键的所有事件都将在同一个任务槽中处理。您可以将
ValueState
视为分布式(分片)键/值存储,其中值的类型为a。每个任务管理器都具有该键/值存储的一个片段的状态(对于不相交的键子集),并处理这些键(仅那些键)的所有事件

例如:在
flatMap1
中,当使用
streamA
中的元素调用
BState.value()
时,Flink运行时将访问当前上下文中的键的
BState
值,这意味着与当前正在处理的
streamA
中的事件的键关联的值。在当前任务中,此状态将始终为本地状态。类似地,
flatmap 2
将始终使用
streamB
中的元素调用


这种设计避免了任务管理器之间的任何耦合,这有利于可伸缩性和性能

两个任务管理器不需要为了状态共享而进行通信——Flink中没有状态共享

下面显示的这三个执行图中的任何一个都是可能的,这取决于您如何安排源的细节。在每个图的左边,我们看到A和B的源操作符,在右边,两个平行的双输入操作符实例通过RichCoFlatMap实现连接

keyBy不是运算符,而是指定源和两个RichCoFlatMap实例的连接方式。它将其安排为哈希连接,对源流进行重新分区

使用这三种场景中的哪一种并不重要,因为在所有三种情况下,keyBy将具有相同的效果,即引导某些键的所有事件到Join1,以及引导其他键的所有事件到Join2

换句话说,对于任何给定的键,该键的所有事件都将在同一个任务槽中处理。您可以将
ValueState
视为分布式(分片)键/值存储,其中值的类型为a。每个任务管理器都具有该键/值存储的一个片段的状态(对于不相交的键子集),并处理这些键(仅那些键)的所有事件

例如:在
flatMap1
中,当使用
streamA
中的元素调用
BState.value()
时,Flink运行时将访问当前上下文中的键的
BState
值,这意味着与事件键关联的值