Hackx's Blog

好男人总被坏女人伤害,好女人总被坏男人伤害,或者好男人和好女人都各自忍受孤独

Apache Flink中事件时间的介绍

一个刽子手的责任,在看准了头颈的分寸,一刀霍下,让鲜血喷起,人头落地。被杀的人究竟有罪或者冤枉,不是刽子手的事情。甚至于即使他明明知道眼前跪着的人其实无辜,也没有人会指责刽子手为凶手。我们可以说,刽子手只是奉命行事,做一天和尚当然就得撞一天钟。应该负责的,是判官;或者,是那个不健全的审判制度;再抽象一点,我们不妨这么说,错在那个封建的社会。 –龙应台 《人在欧洲》

原文地址:https://www.da-platform.com/blog/stream-processing-introduction-event-time-apache-flink

Apache Flink在有状态流处理中支持多个时间概念。本文主要关注Apache Flink对事件时间的支持。在下面的小节中,我们将定义Apache Flink的事件时间是什么,我们将研究流处理框架中不同的时间概念,并描述Flink如何使用水印来度量事件时间的进度。

流处理中的事件时间

顾名思义,Apache Flink中的事件时间是在生产源上生成每个单独事件的时间。在标准场景中,从不同生产者收集的事件(即与移动应用程序、金融交易、应用程序和机器日志、传感器事件等的交互)在其元数据中存储一个时间元素。这个时间表示特定事件在生产源中生成的时间。当应用程序逻辑需要基于事件生成时间的数据进行处理或计算时,有状态流处理和实时计算将使用事件时间。

事件时间、处理时间和摄入时间的不同之处

为了有效地描述Flink如何在流处理中管理不同的时间概念,让我们设想一个场景(如下所示),在这个场景中,一个手机游戏玩家坐地铁去上班。玩家在平台上启动手机游戏,生成的事件被发送到Flink操作符。但是,当玩家在地铁车厢内时,wifi连接丢失,数据存储在移动设备上,没有传输到流处理系统。一旦用户重新上线,设备就会将剩余的数据发送到流媒体基础设施,然后步行到办公室。

source/images/post/

Event-time-FFT-Icon-london-underground

在上面的场景中,移动游戏提供商可能使用基于Apache Flink的实时消息应用程序来分析游戏上的用户活动,并通过推送通知或消息提供实时优惠。这个应用程序可以基于不同的时间概念来处理传入的数据:我们前面描述的事件时间、处理时间以及我们在下一节中描述的摄入时间。

处理时间是指在流处理应用程序中执行特定操作的机器时间。当流处理应用程序使用处理时间时,它使用机器的时钟来运行任何操作。一个5小时处理时间窗口将对完整的5个小时时间间隔内到达操作符的所有事件进行合并。处理时间很简单,不需要流和机器之间的协调,而且它提供了最好的性能和最低的延迟。然而,在分布式系统和上面描述的示例这样的场景中,使用处理时间进行计算可能并不总是最合适的,因为事件将异步或无序地到达操作符。

Event-time-FFT-Icon-Event-time

摄取时间是事件到达流处理应用程序的时间。摄入时间是任何处理延迟及其潜在波动的原因,并且在处理系统“消费”消息时标记时间戳。然后将此时间戳与任何基于时间的操作的特定事件相关联。与处理时间相比,摄入时间提供了更可预测的结果,尽管仍然不是100%准确,因为它不能处理原始时间和无序数据。

与处理时间相比,摄入时间提供了更可预测的结果,因为它在源操作符上一次性分配了一个稳定的时间戳,这使得所有与时间相关的操作都返回到所分配的时间戳。相反,随着处理时间的增加,每个操作符可以根据本地系统时钟将记录分配到不同的窗口。

Apache Flink通过在源上分配自动时间戳和生成自动水印(参见下面),以类似于事件时间的方式处理摄入时间。

Apache Flink中的默认时间是处理时间。但是,如果应用程序异步工作或与分布式系统一起工作,可能需要将Flink设置为事件时间。相对其他两种时间,事件时间将提供最准确的结果,因为,正如我们前面解释的,它在事件或“消息”源生成时分配时间戳。然后,这个时间戳在所有与时间相关的操作中跟踪事件。事件时间由Apache Flink中的水印处理和支持,我们将在下面介绍。

在Apache Flink中,处理时间可以通过以下代码更新为事件时间:

1
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

Flink中的水印和事件时间

水印是Apache Flink在事件时间中度量进展的机制。水印是数据流的一部分,其携带了一个时间戳t。在数据流中,一个水印(t)宣称事件时间已达到时间t,意思就是不应该有更多的元素,其流时间戳t ‘ < = t(即事件时间戳大于或等于水印)。水印对于无序流和不按时间戳排序的异步操作非常重要。通常,水印是一种声明,表示流中的某个特定点,即某个时间戳之前的所有事件都应该已经到达。一旦水印到达操作符,操作符可以将其内部事件时间时钟推进到水印的值。举个例子,在我们使用小时窗口操作的情况下,水印将允许Flink了解特定的小时窗口何时超过小时,以便操作符可以关闭正在运行的现有窗口。

我们之前的一篇文章更详细地描述了这个特性,并在使用Apache Flink处理有状态流的水印时提供了一些有用的观察。

流处理应用程序所选择的时间支持将取决于应用程序的需求和特定的系统特性。为流应用程序选择正确的时间概念至关重要,因为这将最终影响您以后的结果和操作。Apache Flink的设计目的是提供灵活性,并根据应用程序的需求支持不同的时间概念。有关调试窗口和事件时间的更多信息,请阅读Flink文档