Flink系列之时间
Posted Spark高级玩法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flink系列之时间相关的知识,希望对你有一定的参考价值。
一,fink支持的时间
Flink的流式应用支持不同的时间观。
1,处理时间
处理时间是指执行相应操作的机器的系统时间。
当流程序采用处理时间运行时,所有基于时间的操作(如时间窗口)将使用运行各自运算符的机器的系统时钟。例如,每小时处理时间窗口将包括在系统时钟显示一个小时的时间之间到达特定操作之间的所有记录。
处理时间是最简单的时间概念,不需要流和机器之间的协调。它提供最好的性能和最低的延迟。然而,在分布式和异步环境中,处理时间不能提供决定论,因为它易受记录到达系统(例如从消息队列)到达的速度的影响,也与记录在系统内部的操作算子之间流动的速度有关。
2,事件时间
事件时间是每个事件在其生产设备上发生的时间。这个时间通常是嵌入在事件中他们进入fink和事件的时间戳可以从事件中提取。每小时事件时间窗口将包含所有事件,该事件都包含到该时间的事件时间戳,而不管事件何时到达,以及它们到达的顺序。
事件时间给出正确的结果,即使在乱序的事件,迟滞的事件,或从备份或持久的日志的回放数据。使用事件时间,时间的进展取决于数据,而不是墙上的时钟。事件时间程序必须指定如何生成事件时间Watermarks,这是在事件时间内发出信号的机制。该机制如下所述。
事件时间处理通常会产生一定的延迟,这是因为它具有等待后期事件和无序事件的特定时间的特性。因此,基于事件间的程序常常与处理时间操作相结合。
3,注入时间
注入时间是指事件进入flink的时间。在Sources操作符中每条事件都会获取Sources的当前时间作为时间戳,基于时间的操作(比如windows)会依据这个时间戳。
注入时间在概念上在事件时间和处理时间之间。与处理时间相比,它稍微更消耗性能些,但是却提供了可预测的结果。因为注入时间使用固定的时间戳(在Sources处一次分配),不同的窗口操作都会使用相同的时间,而使用处理时间每个窗口操作,都可能分配给消息不同的时间窗口(基于本地系统时间)。
与事件时间相比,注入时间程序不能处理任何无需时间或者滞后数据,但是程序不需要指定如何生成watermark。
在内部,注入时间和事件时间非常相似,但是注入时间有自动时间戳分配和自动watermark生成的功能。
二,设定时间特性
一个flink流程序第一部分往往是设置基础时间特性。该设置确定了流的Sources头如何操作(比如是否分配一个时间戳)与此同时确认窗口操作(如KeyedStream.timeWindow(Time.seconds(30)).)如何使用时间的概念。
下面的flink程序展示了以小时时间窗口聚合事件。窗口的行为与时间特性相互适应。
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
// alternatively:
// env.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);
// env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
DataStream<MyEvent> stream = env.addSource(new FlinkKafkaConsumer09<MyEvent>(topic, schema, props));
stream
.keyBy( (event) -> event.getUser() )
.timeWindow(Time.hours(1))
.reduce( (a, b) -> a.add(b) )
.addSink(...);
注意,为了使用事件时间来运行这个例子,程序使用Sources来直接定义数据的事件时间和决定watermark,或者程序在Sources后必须注入一个Timestamp Assigner & Watermark Generator。这些功能主要描述了如何去使用事件时间戳,和事件流展示出来的无序程度。
下面的部分描述了在时间戳和watermark的一般机制。为指导如何在数据流API的使用时间戳分配和Flink watermark生成,后面会出文章介绍。
三,事件时间和watermark
支持事件时间的流处理器需要一种方法来测量时间时间的进展。例如,一个小时窗口windows的操作,当事件时间已经超过一个小时的时候需要通知该操作算子,以便操作算子可以关闭正在进行中的窗口。
事件时间可以独立于处理时间前进。例如在一个程序中,操作算子的当前事件时间可能稍微落后于处理时间(收到事件延迟导致),而两者都以相同的速度进行。另一方面,另一个流程序可能只需要几秒钟的处理时间就可以处理通过几周的事件时间,通过快速处理一些已经缓存在kafka主题(或者另外的消息队列)中的历史数据。
Flink中使用watermark去测量事件时间的进度。Watermark 流作为数据流的一部分,携带一个时间戳 t。一个Watermark(t) 声明事件时间已经到达时间t,意味着已经没有事件时间t1<t的元素在流中存在(也即时间的时间戳应该早于或者等于watermark)。
如下图:
Watermark对于无序流是至关重要的,如下图所示,事件不是根据时间戳排序。一般来说,watermark是一个声明,通过流中的那个点,所有到达某个时间戳的时间应该已经到达,一旦watermark到达操作算子,操作算子就可以提升内部时间到watermark所指定的值。
四,在并行流中的watermark
Watermark是在Source函数中直接或者在其后直接生成。一个源函数的每个并行子任务通常独立的产生watermark。这些watermark定义了特定并行源的事件时间。
当watermark流经流程序时,会调整操作算子中的事件时间至watermark到达的时间。每当操作算子提前它自己的事件时间时,它就会为后继的操作算子生成一个新的下行watermark。
一些操作算子使用多个输入流。例如,union操作,或者keyBy(...)或partition(...)之后的操作.这些操作算子的当前事件时间是所有输入流最小的事件时间。当输入流更新它们的事件时间时,操作算子也会更新。
下图显示了,流经并行流的事件和watermark,以及跟踪事件时间的运算符。
五,迟滞元素
也可能存在违反watermark条件的元素,也即在Watermark(t) 已经发生以后,很多时间戳t1<t的元素也会出现。事实上,在现实设置中,某些元素可能会有任意的延迟,使得所有元素在watermark之前准时到达变得不是很可能。即使延迟是有界的,大量延迟watermark也是不可取的,因为会导致事件时间窗口评估延迟很大。
鉴于这个原因,流式程序可能明确的期待一些延迟的元素。后面会出文章,详细介绍如何在事件时间窗口中处理延迟元素。
六,对比Spark Streaming
对比Spark Streaming可以知道,我们的Spark Streaming支持的时间是处理时间,这在现实生活中,尤其是基于时间序列的事件处理的时候,就略显不足了。所以,在选用流式处理的时候,要结合自己的业务需要。
推荐阅读:
1,
2,
4,
以上是关于Flink系列之时间的主要内容,如果未能解决你的问题,请参考以下文章
Flink源码系列Flink 源码分析之 Client 端启动流程分析