flink forBoundedOutOfOrderness/allowedLateness
区别
在Apache Flink中,allowedLateness和forBoundedOutOfOrderness是与时间窗口和事件时间处理相关的两个概念,它们用于处理乱序事件。
forBoundedOutOfOrderness:
这是一个水印生成策略,用于处理乱序事件流中的事件。在实时流处理中,由于网络延迟、系统故障等原因,数据可能不会按照事件发生的顺序到达。forBoundedOutOfOrderness允许你指定一个最大的乱序时间(称为乱序界限),Flink将使用这个时间来生成水印(Watermarks)。水印是Flink用来追踪事件时间进度的机制,它告诉系统在这个时间戳之前的数据都已经到达,因此窗口可以在水印到达后触发计算。
例如,如果你设置了5秒的乱序界限,那么即使数据晚到5秒,系统也会等待这些数据到达后再进行窗口计算。
allowedLateness:
allowedLateness是指一个窗口在触发后还能够接收延迟数据的时间长度。当一个窗口的水印超过了窗口的结束时间,窗口就会触发计算,但如果设置了allowedLateness,即使窗口已经触发,它仍然可以在一段时间内接收迟到的数据并更新结果。
例如,如果你设置了一个窗口的allowedLateness为10秒,即使窗口已经触发,它仍然会在接下来的10秒内等待迟到的数据。如果在这段时间内有迟到的数据到达,窗口可能会重新计算并更新之前的结果。
总结:
forBoundedOutOfOrderness是设置水印以处理乱序事件,定义了系统在处理事件时可以接受的最大乱序时间。
allowedLateness是在窗口已经触发后,还可以接收迟到事件的时间长度,允许窗口在一定时间内更新已经计算过的结果。
两者的区别在于它们处理事件的时间点不同:forBoundedOutOfOrderness是在窗口触发之前,定义了生成水印的策略;而allowedLateness是在窗口触发之后,定义了窗口可以接收延迟数据的时间。
forBoundedOutOfOrderness
设窗口为5,延迟为3。
假如数据为:0 1 2 5 6 7 3 4 8
则两个窗口为 :
window = TimeWindow{start=0, end=5}
0
1
2
3
4
window = TimeWindow{start=5, end=10}
5
6
7
8
即:5 6 7 的数据不会包含在 TimeWindow{start=0, end=5} 里。
验证程序:
public class FlinkWindowExample {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
DataStreamSource<String> ds = env.socketTextStream("worker1", 7777);
SingleOutputStreamOperator<Integer> watermarks = ds
.map(Integer::parseInt)
.assignTimestampsAndWatermarks(WatermarkStrategy
.<Integer>forBoundedOutOfOrderness(Duration.ofMillis(3))
.withTimestampAssigner((event, timestamp) -> event));
SingleOutputStreamOperator<Integer> windowedStream = watermarks
.windowAll(TumblingEventTimeWindows.of(Time.milliseconds(5)))
.apply(new AllWindowFunction<Integer, Integer, TimeWindow>() {
@Override
public void apply(TimeWindow window, Iterable<Integer> values, Collector<Integer> out) throws Exception {
System.out.println("window = " + window);
for (Integer value : values) {
out.collect(value);
}
}
});
windowedStream.print();
env.execute("Flink Window Example");
}
}
allowedLateness
设窗口为5,延迟为3。
假如数据为:0 1 2 5 6 7 3 4 8
输出:
window = TimeWindow{start=0, end=5}
0
1
2
window = TimeWindow{start=0, end=5}
0
1
2
3
window = TimeWindow{start=0, end=5}
0
1
2
3
4
window = TimeWindow{start=5, end=10}
5
6
7
8
程序:
public class FlinkWindowExample {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
DataStreamSource<String> ds = env.socketTextStream("worker1", 7777);
SingleOutputStreamOperator<Integer> watermarks = ds
.map(Integer::parseInt)
.assignTimestampsAndWatermarks(WatermarkStrategy
.<Integer>forMonotonousTimestamps()
.withTimestampAssigner((event, timestamp) -> event));
SingleOutputStreamOperator<Integer> windowedStream = watermarks
.windowAll(TumblingEventTimeWindows.of(Time.milliseconds(5)))
.allowedLateness(Time.milliseconds(3))
.apply(new AllWindowFunction<Integer, Integer, TimeWindow>() {
@Override
public void apply(TimeWindow window, Iterable<Integer> values, Collector<Integer> out) throws Exception {
System.out.println("window = " + window);
for (Integer value : values) {
out.collect(value);
}
}
});
windowedStream.print();
env.execute("Flink Window Example");
}
}