Apache flink 如何在Flink作业中操作3个数据流?

Apache flink 如何在Flink作业中操作3个数据流?,apache-flink,Apache Flink,我们有3个爪哇POJO class Foo{ int id; String name; List<Bar1> list1; List<Bar2> list2; } class Bar1{ int id; String field_x; String field_y; } class Bar2{ int id; String field_a; String field_b; } 我们的Flink工作中有3个数据流 class Test{ publ

我们有3个爪哇POJO

class Foo{
 int id;
 String name;
 List<Bar1> list1;
 List<Bar2> list2;
}

class Bar1{
 int id;
 String field_x;
 String field_y;
}

class Bar2{
 int id;
 String field_a;
 String field_b;
}
我们的Flink工作中有3个数据流

class Test{
 public static void main(...){
  DataStream<Foo> ds1 = ...;
  DataStream<Bar1> ds2 = ...;
  DataStream<Bar2> ds3 = ...;
 }
}
对于每个id,只有一个Foo对象,而Bar1和Bar2对象可以是多个

我们要做的是,对于ds1中的每个Foo,在ds2中找到具有相同id的所有Bar1并将它们放入列表1,在ds3中找到具有相同id的所有Bar2并将它们放入列表2


最好的方法是什么?

Flink的数据流操作符最多支持两个输入流。 在三个流上实现操作有两种常见方法:

使用两个二进制操作。这在您的案例中非常简单,因为Bar1和Bar2彼此不相关。这大致如下所示: 数据流withList1=ds1 .connectds2.keyByid,id 过程 //您的处理逻辑 新的协处理函数{…}; 数据流withList1AndList2=withList1 .connectds3.keyByid,id 过程 //您的处理逻辑 新的协处理函数{…}; 通过将所有三个流合并为具有公共数据类型的单个流,例如具有三个字段foo、bar1和bar2的POJO,其中仅使用一个字段,并使用具有单个输入的运算符来处理合并流。 //将Foo映射到CommonType DataStream common1=ds1.mapnew映射函数{…}; //将Bar1映射到CommonType DataStream common2=ds2.mapnew映射函数{…}; //将Bar2映射到CommonType DataStream common3=ds3.mapnew映射函数{…}; 具有List1AndList2=ds1.unionds2和ds3的数据流 凯比先生 过程 //您的处理逻辑 新的KeyedProcessFunction{…}; 您也可以将ds2和ds3合并并使用二进制运算符

更大的问题可能是确定何时接收到所有Bar1和Bar2事件,以便您可以发出结果。同样,根据您的用例,还有一些选项

如果Foo知道它需要等待多少Bar1和Bar2,那么解决方案是显而易见的。 如果Foo不知道要等待多少个事件,您可以尝试发送一个通知,表示已发送最后一个Bar1或Bar2。 如果您知道所有Bar1或Bar2应在x秒/分钟/等时间内到达,也可以使用超时。
谢谢你的回答,因为我对Flink很陌生,你能不能提供一个代码片段,这将非常有帮助。我已经添加了一些片段以使整个流程清晰。Hi Fabian,我在编写过程中仍然有困难。。。。我已经知道了当有一个时间窗口时该如何做,因为它有一个迭代器,我可以通过迭代器。但我不知道在没有时间窗口的情况下该怎么办。你能帮我举个例子吗?假设所有Bar1或Bar2应在3分钟内到达。非常感谢。这个想法是通过上下文对象使用计时器。当您收到一个Foo对象时,您将其存储在state中,并提前3分钟注册一个计时器。在这3分钟内,将所有Bar1和Bar2对象添加到Foo对象,即更新状态。3分钟后,计时器调用onTimer回调方法,发出Foo对象并清除状态。明白了,我想我需要学习状态相关知识。再次感谢你!