Flink Windows边界,水印,事件时间戳和处理时间

时间:2019-07-20 01:01:55

标签: apache-flink flink-streaming watermark stream-processing

问题定义与确立概念

假设我们有一个 TumblingEventTimeWindow ,其大小为5分钟。我们有包含 2个基本信息信息的事件:

  • 号码
  • 事件时间戳

在此示例中,我们在 12:00 PM工作者计算机的挂钟时间上启动了 Flink 拓扑(当然,工作者可以没有同步时钟,但这是超出此问题的范围)。该拓扑包含一个处理操作员,其负责总结属于每个窗口的事件的值以及与该问题无关的KAFKA接收器。

  • 此窗口有一个BoundedOutOfOrdernessTimestampExtractor,允许的延迟时间为一分钟
  • 水印:据我了解,Flink和Spark结构化流中的水印定义为( max-event-timestamp-seen-so-far-allowed-lateness ) 。事件时间戳小于或等于此水印的任何事件都将被丢弃并在结果计算中忽略。

第1部分(确定窗口的边界)

快乐(实时)路径

在这种情况下,几个事件到达 Flink运算符,它们的事件时间戳跨越12:01 - 12:09。此外,事件时间戳与我们的处理时间相对应(在下面的X轴中显示)。由于我们正在处理 EVENT_TIME 特性,因此应通过事件的 event timestamp 确定事件是否属于某个事件。

enter image description here

旧数据涌入

在该流程中,我假定了两个滚动窗口边界,分别是12:00 -- 12:0512:05 -- 12:10因为我们已在 12:00 开始执行拓扑。如果该假设是正确的(我希望不是),那么在回填情况下会发生什么情况,在这种情况下,发生了多个 old 事件且带有更旧的事件时间戳,我们又在 12:00 开始了拓扑? (年龄足够大,以致我们的迟到津贴不包括这些费用)。类似于以下内容:

enter image description here

  1. 如果这样,那么我们的事件当然不会在任何窗口中捕获,因此,我再次希望那不是行为:)
  2. 另一种选择是通过到达事件的事件时间戳确定窗口的边界。如果是这样,那将如何工作?注意到的最小事件时间戳成为第一个窗口的开始,然后根据其大小(在这种情况下为 5分钟)从第一个窗口开始,是否确定了边界?因为这种方法也会有缺陷和漏洞。您能解释一下它是如何工作的以及如何确定窗口的边界吗?

回填事件涌入

上一个问题的答案也将解决此问题,但是我认为在此处明确提及它会有所帮助。假设我有这个 TumblingEventTimeWindow ,大​​小为5分钟。然后在 12:00 ,我启动了一项回填工作,该工作将许多事件赶往Flink运算符,该运算符的时间戳覆盖范围10:02 - 10:59;但这是一项回填工作,因此整个执行过程大约需要 3分钟

作业会分配 12个单独的窗口并根据事件的事件时间戳正确地填充它们吗?这 12个窗口的边界是什么?我是否会以 12个输出事件结尾,每个事件具有每个分配窗口的总结值?

第2部分(此类有状态运算符的单元/集成测试)

对于这种逻辑和运算符的自动化测试,我也有一些担忧。操纵处理时间的最佳方法是触发某些行为,从而塑造所需窗口的边界以进行测试。特别是因为到目前为止,我所读到的关于利用Test Harnesses的内容似乎有点令人困惑,并且可能会导致一些混乱的代码,而这些代码并不那么容易阅读:

参考

我在这方面学到的大部分知识和一些困惑的根源可以在以下地方找到:

非常感谢您的帮助,如果您对这些概念及其内部运作有更好的参考,请告诉我。

@snntrable回答后更新

  

如果您使用事件时间语义来运行Job,则在窗口运算符上的处理时间是完全不相关的

那是正确的,我理解这一部分。一旦处理了EVENT_TIME特性,您就在语义/逻辑上与处理时间脱节了。我延长处理时间的原因是我对以下关键问题感到困惑,这对我来说仍然是个谜:

窗口边界如何计算?!

也非常感谢您澄清out-of-ordernesslateness之间的区别。我正在处理的代码完全被误用(使从BoundedOutOfOrdernessTimestampExtractor继承的类的构造函数参数被命名为maxLatency)使我失望:/

考虑到这一点,让我看看我是否能够正确理解水印的计算方式何时丢弃事件 strong>(或侧面输出):

  • 乱序分配器
    • 当前水印= max-event-time-seen-so-far - max-out-of-orderness-allowed
  • 允许延迟
    • 当前水印= max-event-time-seen-so-far - allowed-lateness
  • 常规流量
    • 当前水印= max-event-time-seen-so-far

任何一种情况下,无论其事件时间戳小于或等于current-watermark 的事件,被丢弃(侧面输出),对吗?!

这带来了一个新问题。您何时想使用out of orderness而不是lateness?由于在这些情况下当前水印计算(在数学上)可以是相同的。当您同时使用两者时会发生什么(甚至有意义)?!

返回Windows边界

这仍然是我的主要谜团。鉴于以上所有讨论,让我们回顾我提供的具体示例,看看如何确定窗口的边界。假设我们有以下情形(事件的形式为(value, timestamp)):

  • 操作员于 12:00 PM (即处理时间)开始了
  • 事件按以下顺序到达操作员
    • (1, 8:29
    • (5, 8:26
    • (3, 9:48
    • (7, 9:46
  • 我们有一个 TumblingEventTimeWindow ,大​​小为 5分钟
    • 该窗口应用于DataStream的{​​{1}},其持续时间为 2分钟 BoundedOutOfOrdernessTimestampExtractor
  • ,该窗口配置了{strong> 1分钟
  • maxOutOfOrderness

注意:如果您不能同时拥有allowedLatenessout of orderness,或者没有有意义,请考虑lateness在上面的示例中。

最后,能否请您布置窗口,将为其分配一些事件,请指定这些窗口的边界开始结束窗口的时间戳)。我假设边界也由事件的时间戳确定,但是要在像这样的具体示例中弄清楚边界是很棘手的。

再次,非常感谢,非常感谢您的帮助:)

1 个答案:

答案 0 :(得分:0)

  

水印:据我了解,Flink和Spark结构化流中的水印定义为(最大事件时间戳,到目前为止可以看到-允许延迟)。任何事件时间戳小于或等于该水印的事件都将被丢弃并在结果计算中忽略。

这是不正确的,可能是造成混淆的原因。乱序和延迟是Flink中的不同概念。使用BoundedOutOfOrdernessTimestampExtractor时,水印为max-event-timestamp-seen-so-far - max-out-of-orderness。 Flink文档[1]中有更多关于允许延迟的信息。

如果您使用事件时间语义来运行Job,则在窗口运算符上的处理时间是完全不相关的:

  • 事件将根据事件时间时间戳分配给其窗口
  • 一旦水印达到其最大时间戳(window end time -1),就会触发
  • 时间窗口。
  • 时间戳早于current watermark - allowed lateness的事件将被丢弃或发送到后期数据端输出[1]

这意味着,如果您在12:00 pm(处理时间)开始工作并开始提取过去的数据,则水印也会(甚至更早)出现。因此,配置的allowedLateness是无关紧要的,因为相对于偶数时间而言,数据并不晚。

另一方面,如果您首先从12:00 pm提取一些数据,然后从10:00 pm提取数据,则水印在提取旧数据之前已经提前到〜12:00pm。在这种情况下,晚上10:00起的数据将是“晚期”。如果它晚于配置的allowedLateness(默认= 0),则将其丢弃(默认)或发送到侧面输出(如果已配置)[1]。

希望这会有所帮助。

康斯坦丁

[1] https://ci.apache.org/projects/flink/flink-docs-release-1.8/dev/stream/operators/windows.html#allowed-lateness

相关问题