为什么 Apache Flink 需要 Watermarks 来进行事件时间处理?
Why does Apache Flink need Watermarks for Event Time Processing?
谁能正确解释事件时间戳和水印。我从文档中了解到,但不是很清楚。现实生活中的例子或外行定义会有所帮助。另外,如果可能的话,请给出一个例子(连同一些可以解释它的代码片段)。在此先感谢
下面的示例说明了为什么我们需要水印,以及它们是如何工作的。
在这个例子中,我们有一个带有时间戳的事件流,它们到达时有点乱,如下所示。显示的数字是事件时间戳,指示这些事件实际发生的时间。第一个到达的事件发生在时间 4,随后是更早发生的事件,时间 2,依此类推:
··· 23 19 22 24 21 14 17 13 12 15 9 11 7 2 4 →
现在假设我们正在尝试创建一个流排序器。这是一个应用程序,它在流中的每个事件到达时处理它,并发出包含相同事件的新流,但按时间戳排序。
一些观察:
(1) 我们的流排序器看到的第一个元素是 4,但我们不能立即将它作为已排序流的第一个元素释放。它可能已经到达无序,并且更早的事件可能尚未到达。事实上,我们对这个流的未来有了一些神似的知识,我们可以看到我们的流排序器应该至少等到 2 到达才能产生任何结果。
结论:一些缓冲和一些延迟是必要的。
(2) 如果我们做错了,我们可能会永远等待。首先,我们的应用程序看到了时间 4 的事件,然后是时间 2 的事件。时间戳小于 2 的事件会到达吗?可能是。也许不吧。我们可以永远等待,永远看不到 1。
结论:最终我们必须勇敢地发出 2 作为排序流的开始。
(3) 那么我们需要的是某种策略,它定义了对于任何给定的时间戳事件,何时停止等待更早事件的到来。
这正是水印所做的 — 它们定义了何时停止等待更早的事件。
Flink 中的事件时间处理依赖于 watermark 生成器 将特殊时间戳元素插入流中,称为 watermarks.
我们的流排序器什么时候应该停止等待,并推出 2 以开始排序流?当水印以 2 或更大的时间戳到达时。
(4) 我们可以想象不同的策略来决定如何生成水印。
我们知道每个事件都会在一定延迟后到达,并且这些延迟会有所不同,因此有些事件比其他事件延迟得更多。一种简单的方法是假设这些延迟受某个最大延迟的限制。 Flink 将此策略称为 bounded-out-of-orderness watermarking。很容易想象更复杂的加水印方法,但对于许多应用程序来说,固定延迟就足够了。
如果你想构建一个类似于流排序器的应用程序,Flink 的 KeyedProcessFunction
是正确的构建块。它提供对事件时间计时器(即基于水印到达的回调)的访问,并具有用于管理缓冲事件所需状态的挂钩,直到轮到它们被发送到下游。
谁能正确解释事件时间戳和水印。我从文档中了解到,但不是很清楚。现实生活中的例子或外行定义会有所帮助。另外,如果可能的话,请给出一个例子(连同一些可以解释它的代码片段)。在此先感谢
下面的示例说明了为什么我们需要水印,以及它们是如何工作的。
在这个例子中,我们有一个带有时间戳的事件流,它们到达时有点乱,如下所示。显示的数字是事件时间戳,指示这些事件实际发生的时间。第一个到达的事件发生在时间 4,随后是更早发生的事件,时间 2,依此类推:
··· 23 19 22 24 21 14 17 13 12 15 9 11 7 2 4 →
现在假设我们正在尝试创建一个流排序器。这是一个应用程序,它在流中的每个事件到达时处理它,并发出包含相同事件的新流,但按时间戳排序。
一些观察:
(1) 我们的流排序器看到的第一个元素是 4,但我们不能立即将它作为已排序流的第一个元素释放。它可能已经到达无序,并且更早的事件可能尚未到达。事实上,我们对这个流的未来有了一些神似的知识,我们可以看到我们的流排序器应该至少等到 2 到达才能产生任何结果。
结论:一些缓冲和一些延迟是必要的。
(2) 如果我们做错了,我们可能会永远等待。首先,我们的应用程序看到了时间 4 的事件,然后是时间 2 的事件。时间戳小于 2 的事件会到达吗?可能是。也许不吧。我们可以永远等待,永远看不到 1。
结论:最终我们必须勇敢地发出 2 作为排序流的开始。
(3) 那么我们需要的是某种策略,它定义了对于任何给定的时间戳事件,何时停止等待更早事件的到来。
这正是水印所做的 — 它们定义了何时停止等待更早的事件。
Flink 中的事件时间处理依赖于 watermark 生成器 将特殊时间戳元素插入流中,称为 watermarks.
我们的流排序器什么时候应该停止等待,并推出 2 以开始排序流?当水印以 2 或更大的时间戳到达时。
(4) 我们可以想象不同的策略来决定如何生成水印。
我们知道每个事件都会在一定延迟后到达,并且这些延迟会有所不同,因此有些事件比其他事件延迟得更多。一种简单的方法是假设这些延迟受某个最大延迟的限制。 Flink 将此策略称为 bounded-out-of-orderness watermarking。很容易想象更复杂的加水印方法,但对于许多应用程序来说,固定延迟就足够了。
如果你想构建一个类似于流排序器的应用程序,Flink 的 KeyedProcessFunction
是正确的构建块。它提供对事件时间计时器(即基于水印到达的回调)的访问,并具有用于管理缓冲事件所需状态的挂钩,直到轮到它们被发送到下游。