如何使用 Apache Flink DataStream API 输出事件对流?
How to use Apache Flink DataStream API to output stream of event pairs?
一只鞋子(一个事件)被定义为它的颜色和isLeft
(如果鞋子是左腿的那么isLeft=true
否则false
)。
Tuple2<String, Boolean> leftBlueShoe = Tuple2.of("blue", true);
Tuple2<String, Boolean> rightBlueShoe = Tuple2.of("blue", false);
// unbounded stream of shoes is as follows
DataStream<Tuple2<String, Boolean>> streamOfShoes = ...
// somthing like - env.fromElements(leftBlueShoe, rightRedShoe, leftGreenShoe, rightBlueShoe, ...);
如何组成一双相同颜色的鞋子并期望匹配的鞋子立即发出,不匹配的鞋子等待它的鞋子直到window结束。
DataStream<Tuple5<String, Boolean, String, Boolean, String>> shoePairs = ...
// few events from shoePairs stream:
Tuple5<> shoePair = Tuple5.of("blue", true, "blue", false, "pairFound");
Tuple5<> notShoePair= Tuple5.of("red", true, "red", false, "pairNotFound"); // Even if pair not found in window we tagged and kept in stream
尝试过的方法(忽略这个以避免混淆):
通过将流分成左右两部分并window连接(会产生成本吗?)
TumblingWindowJoin: 窗口函数无法处理不匹配的对。 window 过去后那只鞋丢了。
CoGroupFunction: Window does not trigger for last event. Full Code
Low-level Joins:即CoProcessFunction()
。不确定是否有帮助?
使用 TumblingProcessingTimeWindow
和 apply()
中的自定义连接逻辑在同一流上开窗。 window 即使所有事件都配对也不会立即触发
Flink training is about finding event pairs; it's similar in spirit to what you're asking for. See the Rides and Fares Exercise 中的练习之一,它使用 RichCoFlatMapFunction
进行配对。
那里的解决方案假定完美配对始终是可能的,因此它不解决不匹配配对的情况。但是您可以找到更进一步的变体 here。此示例使用 CoProcessFunction
中的计时器来检测不匹配的对。
其他要点:
将流分成左子流和右子流的成本应该可以忽略不计。
我认为 CoGroupFunction
应该可以。如果你试过这个但它似乎没有工作,也许你正在使用事件时间 windowing 并且最后的水印丢失,阻止 window 被关闭。
更新:
查看您的代码后,我发现实现中存在问题。您的时间戳提取器使用系统时钟而不是事件中的时间戳。这会给你一些类似于(但比)使用处理时间的东西。我说 "worse than processing time" 是因为您允许事件乱序,这会增加延迟,并且它会阻止 window 关闭,直到事件充分超出 window 的结尾点到了。这意味着最后一个 window 永远不会被触发。
作为测试,尝试将时间特性切换为处理时间,删除 assignTimestampsAndWatermarks
,然后查看 CoGroupFunction 是否正常工作。您也可以使用摄取时间,只要您删除水印并让 Flink 处理它(处理时间水印无关紧要;摄取时间 Flink 会为您添加水印,除非您覆盖它)。
如果您想在应用程序中使用事件时间,请在测试中使用有限源。当有限源(例如从文件或集合中读取)到达其输入的末尾时,它们会通过作业发送一个非常大的水印,从而关闭所有打开的 windows。
一只鞋子(一个事件)被定义为它的颜色和isLeft
(如果鞋子是左腿的那么isLeft=true
否则false
)。
Tuple2<String, Boolean> leftBlueShoe = Tuple2.of("blue", true);
Tuple2<String, Boolean> rightBlueShoe = Tuple2.of("blue", false);
// unbounded stream of shoes is as follows
DataStream<Tuple2<String, Boolean>> streamOfShoes = ...
// somthing like - env.fromElements(leftBlueShoe, rightRedShoe, leftGreenShoe, rightBlueShoe, ...);
如何组成一双相同颜色的鞋子并期望匹配的鞋子立即发出,不匹配的鞋子等待它的鞋子直到window结束。
DataStream<Tuple5<String, Boolean, String, Boolean, String>> shoePairs = ...
// few events from shoePairs stream:
Tuple5<> shoePair = Tuple5.of("blue", true, "blue", false, "pairFound");
Tuple5<> notShoePair= Tuple5.of("red", true, "red", false, "pairNotFound"); // Even if pair not found in window we tagged and kept in stream
尝试过的方法(忽略这个以避免混淆):
通过将流分成左右两部分并window连接(会产生成本吗?)
TumblingWindowJoin: 窗口函数无法处理不匹配的对。 window 过去后那只鞋丢了。
CoGroupFunction: Window does not trigger for last event. Full Code
Low-level Joins:即
CoProcessFunction()
。不确定是否有帮助?
使用
TumblingProcessingTimeWindow
和apply()
中的自定义连接逻辑在同一流上开窗。 window 即使所有事件都配对也不会立即触发
Flink training is about finding event pairs; it's similar in spirit to what you're asking for. See the Rides and Fares Exercise 中的练习之一,它使用 RichCoFlatMapFunction
进行配对。
那里的解决方案假定完美配对始终是可能的,因此它不解决不匹配配对的情况。但是您可以找到更进一步的变体 here。此示例使用 CoProcessFunction
中的计时器来检测不匹配的对。
其他要点:
将流分成左子流和右子流的成本应该可以忽略不计。
我认为 CoGroupFunction
应该可以。如果你试过这个但它似乎没有工作,也许你正在使用事件时间 windowing 并且最后的水印丢失,阻止 window 被关闭。
更新:
查看您的代码后,我发现实现中存在问题。您的时间戳提取器使用系统时钟而不是事件中的时间戳。这会给你一些类似于(但比)使用处理时间的东西。我说 "worse than processing time" 是因为您允许事件乱序,这会增加延迟,并且它会阻止 window 关闭,直到事件充分超出 window 的结尾点到了。这意味着最后一个 window 永远不会被触发。
作为测试,尝试将时间特性切换为处理时间,删除 assignTimestampsAndWatermarks
,然后查看 CoGroupFunction 是否正常工作。您也可以使用摄取时间,只要您删除水印并让 Flink 处理它(处理时间水印无关紧要;摄取时间 Flink 会为您添加水印,除非您覆盖它)。
如果您想在应用程序中使用事件时间,请在测试中使用有限源。当有限源(例如从文件或集合中读取)到达其输入的末尾时,它们会通过作业发送一个非常大的水印,从而关闭所有打开的 windows。