Apache Flink 学习:DataStream Api 中 EventTime

Apache Flink 学习:DataStream Api 中 EventTime

时间

Processing time

处理时间是指执行相应操作的机器的系统时间

Event time

事件时间是每个事件在其生产设备(生产event的设备,手机等的源头设备)上发生的时间

Event Time 和 Watermark

Flink中测量事件时间进度的机制是Watermark。Watermark作为数据流的一部分流动,并带有时间戳t。Watermark(t)声明该流中的 Event Time 已达到时间t,这意味着流中不应再有时间戳t’<=t的元素(即 Event Time 早于或等于 Watermark 的事件)

下图显示了具有时间戳的事件流,以及内联流动的水印。在这个例子中,事件是有序的,这意味着 Watermark 只是流中的周期性标记。

顺序流的Watermark

Watermark对于无序流是至关重要的,如下所示,其中事件到达顺序不是按时间戳顺序。Watermark代表通过流中的该点,这个时间戳之前的事件都应该到达了。一旦Watermark到达算子,算子就可以将其内部事件时钟更新到Watermark的值。

无序流的Watermark

并行流的 Watermarks

Watermark 在源数据 Function 处生成,或直接在源数据 Function 之后生成。源数据 Function 的每个并行子任务通常独立生成其 Watermark。这些 Watermark 定义并行源数据的 Event Time。

当 Watermark 流过程序时,会更新到达算子的 Event Time,当一个 Watermark 更新了算子的 Event Time 时,它会为其下游的后续算子生成一个新的 Watermark。

某些算子消费多个输入流,例如:union 算子或者跟在 keyBy,partition 算子的之后的算子。这样的算子的 Event Time 是所有输入 stream 中最小的 Watermark,即:
Operator Event Time = min(Input Stream 1 Watermark, Input Stream 2 Watermark…)
算子会跟着输入流 Watermark 的更新来更新算子自己的 Event Time。

下图显示了流经并行流的事件和 Watermark 以及算子获取 Event Time 的示例。

并行流的Watermarks

注意,Kafka支持分区 Watermark

Ingestion time

注入时间是事件进入Flink Job的时间。在源Operator处,每条Operator获取源数据的时间作为Ingestion time时间戳

生成 Timestamps 和 Watermarks

分配 Timestamps

数据流源生成 Timestamps 和 Watermarks

数据源可以直接为它们产生的数据分配 Timestamp,并且他们也能发送 Watermark。这样做的话,在后面的处理中就没必要再去定义 Timestamp 分配器了,需要注意的是:如果在后面的处理中使用了一个 timestamp 分配器,由数据源提供的任何 timestamp 和 watermark 都会被重写。

Timestamp 分配器 / Watermark生成器

Timestamp 分配器获取一个流并生成一个新的带有 Timestamp 元素和 Watermark 的流。如果上游的原始数据流已经有 Timestamp 或 Watermark,则 Timestamp 分配器将覆盖上游的 Timestamp 或 Watermark

Timestamp 分配器通常在数据源之后立即指定,但这并不是严格要求的。通常是在 Timestamp 分配器之前先解析(MapFunction)和过滤(FilterFunction)数据源。在任何情况下,都需要在基于 Event Time 算子(例如 window 操作)运行之前指定 Timestamp 分配程序。
有一个特殊情况,当使用 Kafka 作为流作业的数据源时,Flink 允许在数据源内部指定 Timestamp 分配器和 Watermark 生成器。更多关于如何进行的信息请参考Kafka Connector的文档。

直接在FlinkKafkaConsumer010上面使用assignTimestampsAndWatermarks可以根据kafka source的partitions的特性进行设置Timestamps和Watermarks,让用户做一些特殊的处理

Running timestamp extractors / watermark generators directly inside the Kafka source, per Kafka
partition, allows users to let them exploit the per-partition characteristics.

Kafka 分区的 Timestamp

当使用 Apache Kafka 作为数据源时,每个 Kafka 分区可能有一个简单的 Event Time 模式(递增的时间戳或有界无序)。然而,当 Flink Job 使用来自Kafka的流时,多个分区常常并行消费,每一个 operator 算子并行消费时就会破坏各个分区的时间模式(这是 Kafka 客户端消费 Kafka 数据必然发生的)。

在这种情况下,可以使用 Flink’s Kafka-partition-aware watermark generation,使用该功能,每个 Kafka 分区在 Kafka consumer 内部生成 Watermark,每个分区合并 Watermark 的方式与流 shuffles 时合并 Watermark 的方式相同。

例如,如果事件时间戳严格按照 Kafka 分区递增,则使用递增时间戳 Watermark 生成器生成每个分区的 Watermark 将是完美的全局 Watermark。

下图显示了如何使用 Flink’s Kafka-partition-aware watermark generation,以及在这种情况下 Watermark 如何通过流数据流传播。

KafkaSource多分区Watermark