首页 > 解决方案 > 结合会话和翻转窗口:与每个键的第一个事件对齐的时间窗口

问题描述

我在这里阅读了 flink 的窗口分配器:https ://ci.apache.org/projects/flink/flink-docs-stable/dev/stream/operators/windows.html#window-assigners ,但我找不到任何我的问题的解决方案。

作为我项目的一部分,我需要一个窗口,计时器将在给定密钥的第一个元素的情况下启动,并将在 X 分钟后关闭并准备好处理。例如:

第一个 keyA 出现在 (hh:mm:ss) 00:00:02,我希望所有 keyA 都将窗口直到 00:01:02,然后只有当 keyA 作为输入时,1 分钟的计时器才会再次启动。

是否可以在 flink 中做类似的事情?有解决方法吗?希望我说得够清楚。

标签: streamstreamingapache-flinkflink-streaming

解决方案


一般来说,实现与第一个事件而不是与纪元对齐的键控窗口非常困难,我相信这就是为什么 Flink 的窗口 API 不支持这一点。问题在于,对于使用事件时间处理的无序流,随着较早的事件到达,您可能需要修改窗口何时开始以及何时结束的概念。例如,如果第一个 keyA 在 00:00:02 到达,但过了一段时间,带有 keyA 的事件以 00:00:01 的时间戳到达,现在突然窗口应该在 00:01:01 结束,而不是00:01:02。如果与窗口长度相比,无序性很大,那么处理就会变得相当复杂——例如,假设 00:00:01 的事件在 00:00:02 的事件后 2 分钟到达。

我不会尝试使用窗口 API 来实现这一点,而是使用KeyedProcessFunction. 如果您只需要支持处理时间窗口,那么这些关于无序的担忧不适用,并且解决方案可以相当简单。将一个对象保持在键控状态就足够了,这可能是一个包含窗口中所有事件的列表,也可能是一个计数器或其他聚合器,具体取决于您要完成的任务。

当事件到达时,如果状态(对于此键)为空,则此键没有打开窗口。初始化状态(即,创建一个新的空列表,或将计数器设置为零),并创建一个 Timer 以在适当的时间触发。然后不管状态是否为空,将传入事件添加到状态(即,将其附加到列表中,或增加计数器)。

当计时器触发时,发出窗口的结果并将状态重置为空。

另一方面,如果您想对事件时间窗口执行此操作,请首先对流进行排序,然后使用相同的方法。请注意,您将无法处理延迟事件,因此请相应地计划您的水印(将延迟事件的可能性降低到可管理的水平),或者进行更复杂的实现。


推荐阅读