考虑一下,我有一个数据流,其中包含事件时间数据。我想在8毫秒的窗口时间内收集输入数据流,并减少每个窗口数据。我使用以下代码来做到这一点:
aggregatedTuple
.keyBy( 0).timeWindow(Time.milliseconds(8))
.reduce(new ReduceFunction<Tuple2<Long, JSONObject>>()
点::数据流的关键是处理时间的时间戳,该时间戳映射到处理毫秒的时间戳的最后8个子整数,例如1531569851297
将映射到1531569851296
。
但是数据流可能延迟到达,并输入错误的窗口时间。例如,假设我将窗口时间设置为8毫秒。如果数据按顺序进入Flink引擎,或者至少延迟小于窗口时间(8毫秒),这将是最好的情况。但是,假设数据流事件时间(也就是数据流中的字段)以30毫秒的延迟到达。因此它将进入错误的窗口,并且我认为如果我检查每个数据流的事件时间,因为它想进入窗口,因此可以过滤这么晚的数据。 所以我有两个问题:
答案 0 :(得分:0)
Flink具有两个不同的相关抽象,它们处理具有事件时间时间戳的流计算窗口化分析的不同方面:水印和允许延迟。
首先,水印,它们在处理事件时间数据时都会起作用(无论您是否使用Windows)。水印为Flink提供有关事件时间进度的信息,并为应用程序编写者提供了一种处理乱序数据的方法。水印与数据流一起流动,每个水印都标记数据流中的一个位置并带有时间戳。水印表示断言,在流中的那个点上,流现在(可能)已完成到该时间戳记;换句话说,跟随水印的事件不太可能是在流指示的时间之前发生的。水印。最常见的水印策略是使用BoundedOutOfOrdernessTimestampExtractor,它假定事件在某个固定的有限延迟内到达。
现在,这提供了延迟的定义-时间戳小于水印时间戳的事件将被视为 late 。
window API提供了允许延迟的概念,默认情况下将其设置为零。如果允许的延迟大于零,则事件时间窗口的默认触发器将延迟的事件接受到其适当的窗口中,直至允许的延迟的限制。窗口操作将在通常时间触发一次,然后针对每个延迟事件再次触发,直到允许的延迟间隔结束。之后,将简单地丢弃迟到的事件。
How can I filter data stream as it wants to enter the window and check
if the data created at the right timestamp for the window?
Flink的窗口分配器负责将事件分配给适当的窗口-正确的事情将自动发生。新窗口实例将根据需要创建。
How can I gather such late data in a variable to do some processing on them?
您可以在水印中足够大方,以免有任何迟到的数据,和/或将允许的迟到时间配置为足够长以容纳迟到的事件。但是请注意,Flink将被迫保持所有仍在接受后期事件的窗口打开,这将延迟垃圾回收旧窗口并可能消耗大量内存。
请注意,此讨论假设您要使用时间窗口-例如您正在使用的8毫秒长的窗口。 Flink还支持计数窗口(例如将事件分组为100个批次),会话窗口和自定义窗口逻辑。例如,如果使用计数窗口,则水印和延迟不会发挥任何作用。
如果您希望每个键的结果用于分析,请在应用窗口之前使用keyBy按键(例如,按userId)对流进行分区。例如
stream
.keyBy(e -> e.userId)
.timeWindow(Time.seconds(10))
.reduce(...)
将为每个userId生成单独的结果。
一些相关文档: