生成“心跳”类型事件以将事件时间提前

时间:2019-12-06 15:39:07

标签: apache-flink flink-streaming

我正在构建Flink流应用程序,并且希望使用事件时间,因为它可以确保所有设置的计时器都将在历史数据失败或重播时确定性地触发。事件时间的问题是时间只有在事件发生时才向前移动。我们的数据源(物理传感器)有时只生成很少的数据,因此有时单个数据点可能会打开一个五分钟的聚合窗口,但是下一个数据点是20分钟后的数据,因此窗口关闭并在很晚的时候发出输出记录。

为此,我们提出的解决方案是使用安排为每X分钟运行一次的AWS Lambda函数,该函数将虚拟事件输出到Flink读取的Kinesis流中,从而迫使生成水印,从而提前时间。

我担心的是,这仅在水印确实是全局的时才有效,这意味着单条心跳消息可以导致水印的产生,从而延长了使用原始数据的Flink应用程序中每个操作员/任务的事件时间从此流。该文档使我相信Flink会从源中读取内容,其中每个并行读取运算符都会生成自己的水印,然后下游运算符(例如窗口)将所看到的各种水印中的最小值最小化。如果是这种情况,这对我来说似乎很麻烦,因为每个并行水印生成器都需要一个虚拟心跳事件,但是我无法控制哪些节点从流中读取我的心跳消息。

所以,我的问题是,下游运营商到底如何使用水印来提前事件时间,并且可以将单个虚拟消息添加到运动流中以在整个ENTIRE Flink应用程序中提前事件时间?

如果没有,我如何强制事件时间向前发展?

1 个答案:

答案 0 :(得分:1)

您是对的;这里有一个问题。由decktape实现的标准定期水印生成器依赖于看到具有较大时间戳的新事件,以推进水印。

有几种解决方法:

  1. 在以1的并行度运行的任务中运行源和水印分配器(然后,如果需要的话,增加其余管道的并行度)。这样,一条心跳消息就足够了。

  2. 广播心跳消息。这样,每个并行实例都将收到它们,并且它们都可以前进其水印。

  3. 代替心跳消息,实现水印生成器,该生成器使用处理时间计时器人为地推进水印,尽管缺少传入事件。有关示例,请参见https://github.com/aljoscha/flink/blob/6e4419e550caa0e5b162bc0d2ccc43f6b0b3860f/flink-streaming-java/src/main/java/org/apache/flink/streaming/api/functions/timestamps/ProcessingTimeTrailingBoundedOutOfOrdernessTimestampExtractor.java

请注意,这种第三种方法不太理想,因为它与处理时间形成了耦合,从而消除了纯事件时间方法的某些核心优势。

如果使用心跳信号源,则需要为返回MAX_WATERMARK的其他(有时是空闲的)源实现水印生成器。否则,此流中的水印将阻止整个水印。

此外,AWS Lambda感觉有点过分。您可以实现一个简单的自定义Flink源来创建心跳事件。