当使用事件时间窗口时,可能会出现元素到达晚的情况,也就是说,Flink用来跟踪事件时间进程的watermark已经超过了元素所属窗口的结束时间戳。有关Flink如何处理事件时间的详细讨论,请参阅event time ,特别是late elements元素。
默认情况下,当水印超过窗口的末端时将删除晚期元素。但是,Flink允许指定窗口操作符的最大允许延迟时间。允许延迟指定元素在被删除之前可以延迟多长时间,其默认值为0。到达的元素在水印经过窗口末端之后,但在它经过窗口末端加上允许的延迟之前,仍然被添加到窗口中。根据所使用的触发器,迟来但未删除的元素可能会导致窗口再次触发。这就是EventTimeTrigger的情况。
为了使这个工作,Flink保持窗口的状态直到它们允许的延迟过期。一旦发生这种情况,Flink就会删除窗口并删除其状态,这在window Lifecycle一节中也有描述。
默认情况下,允许的延迟设置为0。也就是说,到达水印后面的元素将被删除。
代码语言:javascript复制DataStream<T> input = ...;
input
.keyBy(<key selector>)
.window(<window assigner>)
.allowedLateness(<time>)
.<windowed transformation>(<window function>);
当使用 GlobalWindows 窗口分配程序时,任何数据都不会被认为是迟到的,因为全局窗口的结束时间戳是
Long.MAX_VALUE
。
将迟到的数据作为侧输出流
使用Flink的侧输出特性,您可以得到一个延迟丢弃的数据流。
首先需要指定想要在窗口流上使用sideOutputLateData(OutputTag)
获取延迟数据。然后,你可以在窗口操作的结果上获得侧输出流:
final OutputTag<T> lateOutputTag = new OutputTag<T>("late-data"){};
DataStream<T> input = ...;
SingleOutputStreamOperator<T> result = input
.keyBy(<key selector>)
.window(<window assigner>)
.allowedLateness(<time>)
.sideOutputLateData(lateOutputTag)
.<windowed transformation>(<window function>);
DataStream<T> lateStream = result.getSideOutput(lateOutputTag);
迟到元素考虑
当指定一个允许的延迟大于0时,在watermark通过窗口结束后将保留窗口及其内容。在这些情况下,当一个迟到但没有被删除的元素到达时,它可能会触发对窗口的另一次触发。这些触发被称为延迟触发,因为它们是由延迟事件触发的,与主触发相反,主触发是窗口的第一次触发。对于会话窗口,延迟触发可能进一步导致窗口合并,因为它们可能“桥接”两个已存在的、未合并的窗口之间的间隙。