返回
迟到数据处理:Event Time语义下Flink的三种方式
见解分享
2023-09-28 09:31:54
在Event Time语义下,Flink使用Watermark来判断数据是否迟到。一个迟到元素是指元素到达窗口算子时,该元素本该被分配到某个窗口,但由于延迟,窗口已经触发计算。目前Flink有三种处理迟到数据的方式:
丢弃数据
如果不做其他操作,默认情况下迟到数据会被直接丢弃。这种方式简单粗暴,但可能会导致数据丢失。如果迟到数据非常重要,则不适合使用这种方式。
允许迟到数据
Flink允许在窗口触发计算后继续接收迟到数据,并将其分配到相应的窗口。这种方式可以保证数据不会丢失,但可能会导致窗口计算结果不准确。如果迟到数据量很大,则可能会对窗口计算性能产生影响。
侧输出流
Flink可以通过侧输出流将迟到数据输出到单独的流中。这种方式可以保证数据不会丢失,也不会影响窗口计算结果。但是,侧输出流需要额外的处理逻辑,可能会增加程序的复杂性。
这三种处理迟到数据的方式各有优缺点,应根据具体场景选择合适的处理方式。
如果迟到数据非常重要,则应选择允许迟到数据或侧输出流的方式。如果迟到数据不重要,则可以选择丢弃数据的方式。
如果迟到数据量很大,则应选择侧输出流的方式。如果迟到数据量不大,则可以选择允许迟到数据或丢弃数据的方式。
如果窗口计算性能非常重要,则应选择丢弃数据或允许迟到数据的方式。如果窗口计算性能不重要,则可以选择侧输出流的方式。
示例代码
// 丢弃数据
DataStream<Event> inputStream = ...;
DataStream<Event> resultStream = inputStream
.keyBy(Event::getKey)
.window(TumblingEventTimeWindows.of(Time.seconds(10)))
.allowedLateness(Time.seconds(5))
.apply(new WindowFunction<Event, Object, String, TimeWindow>() {
@Override
public void apply(String key, TimeWindow window, Iterable<Event> input, Collector<Object> out) {
// 窗口计算逻辑
}
});
// 允许迟到数据
DataStream<Event> inputStream = ...;
DataStream<Event> resultStream = inputStream
.keyBy(Event::getKey)
.window(TumblingEventTimeWindows.of(Time.seconds(10)))
.allowedLateness(Time.seconds(5))
.apply(new WindowFunction<Event, Object, String, TimeWindow>() {
@Override
public void apply(String key, TimeWindow window, Iterable<Event> input, Collector<Object> out) {
// 窗口计算逻辑
}
})
.trigger(ContinuousEventTimeTrigger.of(Time.seconds(5)));
// 侧输出流
DataStream<Event> inputStream = ...;
DataStream<Event> resultStream = inputStream
.keyBy(Event::getKey)
.window(TumblingEventTimeWindows.of(Time.seconds(10)))
.allowedLateness(Time.seconds(5))
.sideOutputLateData(new OutputTag<Event>("late-data"))
.apply(new WindowFunction<Event, Object, String, TimeWindow>() {
@Override
public void apply(String key, TimeWindow window, Iterable<Event> input, Collector<Object> out) {
// 窗口计算逻辑
}
});
DataStream<Event> lateDataStream = resultStream.getSideOutput(new OutputTag<Event>("late-data"));