joining
窗口连接将共享一个公共键并位于同一窗口中的两个流的元素连接起来。这些窗口可以通过使用窗口分配器来定义,并在来自两个流的元素上进行计算。
然后将两侧的元素传递给用户定义的 JoinFunction
或 FlatJoinFunction
,用户可以在其中输出满足连接条件的结果。
一般用法可以总结如下:
stream.join(otherStream)
.where(<KeySelector>)
.equalTo(<KeySelector>)
.window(<WindowAssigner>)
.apply(<JoinFunction>)
关于语义的一些注意事项:
-
创建两个流的元素的成对组合的行为类似于内连接,这意味着如果一个流中的元素没有来自另一个流的相应元素香连接,则不会输出它们
-
那些确实加入的元素将仍然具有位于相应窗口中的最大时间戳作为其时间戳。例如,一个以
[5,10]
为边界的窗口将导致连接元素的时间戳为9
。
在下一节中,我们将使用一些示例性场景概述不同类型的窗口连接的行为。
滚动窗口连接
当执行翻转窗口连接时,所有具有公共键和公共翻转窗口的元素作为成对组合连接并传递给 JoinFunction 或 FlatJoinFunction。因为这就像一个内部连接,一个流的元素在它们的滚动窗口中没有另一个流的元素将不会被输出!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eyiarMDW-1637135237933)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211117151942091.png)]
如图所示,我们定义了一个大小为 2 毫秒的滚动窗口,这导致窗口的形式为 [0,1], [2,3], … 图像显示了所有元素的成对组合在将传递给 JoinFunction 的每个窗口中。请注意,在翻滚窗口 [6,7] 中没有发射任何内容,因为绿色流中不存在要与橙色元素 ⑥ 和 ⑦ 连接的元素。
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
...
DataStream<Integer> orangeStream = ...
DataStream<Integer> greenStream = ...
orangeStream.join(greenStream)
.where(<KeySelector>)
.equalTo(<KeySelector>)
.window(TumblingEventTimeWindows.of(Time.milliseconds(2)))
.apply (new JoinFunction<Integer, Integer, String> (){
@Override
public String join(Integer first, Integer second) {
return first + "," + second;
}
});
滑动窗口连接
当执行滑动窗口连接时,所有具有公共键和公共滑动窗口的元素作为成对组合连接并传递给 JoinFunction 或 FlatJoinFunction。在当前滑动窗口中没有来自另一个流的元素的一个流的元素不会被发射!请注意,某些元素可能会连接到一个滑动窗口中,但不会连接到另一个滑动窗口中!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8aW2Kua-1637135237935)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211117153912664.png)]
在这个例子中,我们使用大小为两毫秒的滑动窗口并将它们滑动一毫秒,导致滑动窗口 [-1, 0],[0,1],[1,2],[2,3] ,…… x 轴下方的连接元素是传递给每个滑动窗口的 JoinFunction 的元素。在这里,您还可以看到例如橙色 ② 与窗口 [2,3] 中的绿色 ③ 连接,但未与窗口 [1,2] 中的任何内容连接。
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
...
DataStream<Integer> orangeStream = ...
DataStream<Integer> greenStream = ...
orangeStream.join(greenStream)
.where(<KeySelector>)
.equalTo(<KeySelector>)
.window(SlidingEventTimeWindows.of(Time.milliseconds(2) /* size */, Time.milliseconds(1) /* slide */))
.apply (new JoinFunction<Integer, Integer, String> (){
@Override
public String join(Integer first, Integer second) {
return first + "," + second;
}
});
会话窗口连接
当执行会话窗口连接时,所有具有相同键的元素在“组合”时满足会话标准,以成对组合方式连接并传递到 JoinFunction
或 FlatJoinFunction
。这再次执行内部连接,因此如果存在仅包含来自一个流的元素的会话窗口,则不会发出任何输出!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-876SCmXz-1637135237936)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211117154528058.png)]
这里我们定义了一个会话窗口加入,其中每个会话被至少 1 毫秒的间隙划分。有三个会话,在前两个会话中,来自两个流的连接元素被传递到 JoinFunction。第三个会话中没有绿色流中的元素,所以⑧和⑨没有加入!
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.streaming.api.windowing.assigners.EventTimeSessionWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
...
DataStream<Integer> orangeStream = ...
DataStream<Integer> greenStream = ...
orangeStream.join(greenStream)
.where(<KeySelector>)
.equalTo(<KeySelector>)
.window(EventTimeSessionWindows.withGap(Time.milliseconds(1)))
.apply (new JoinFunction<Integer, Integer, String> (){
@Override
public String join(Integer first, Integer second) {
return first + "," + second;
}
});