一.简介

Flink提供了抽象,允许程序员分配自己的时间戳并发出自己的水印。更具体地说,根据使用情况,可以通过实现AssignerWithPeriodicWatermarks和AssignerWithPunctuatedWatermarks接口之一来实现。简而言之,第一个将定期发出水印,而第二个则根据传入记录的某些属性发出水印,例如,每当流中遇到特殊元素时。

为了进一步简化此类任务的编程工作,Flink附带了一些预先实现的时间戳分配器。

二.时间戳递增的分配器

定期生成水印的最简单的特殊情况是给定源任务看到的时间戳以升序出现的情况。在这种情况下,当前时间戳始终可以充当水印,因为没有更早的时间戳会到达。

请注意,每个并行数据源任务只需要增加时间戳即可。例如,如果在一个特定的设置中一个并行数据源实例读取一个Kafka分区,则仅在每个Kafka分区内将时间戳递增是必要的。每当对并行流进行混洗,连接或合并时,Flink的水印合并机制都会生成正确的水印。

val stream : DataStream[MyEvent] = ...
val withTimestampsAndWatermarks = stream.assignAscendingTimestamps( _.getCreationTime )

三.分配器允许固定的延迟时间

周期性水印生成的另一个情况是水印在流中看到的最大(事件时间)时间戳落后固定时间。这种情况涵盖了预先知道流中可能遇到的最大延迟的场景,例如,当创建包含时间戳的元素的自定义源时,该时间戳在固定时间段内传播以进行测试。对于这些情况,Flink提供了BoundedOutOfOrdernessTimestampExtractor,将用作参数maxOutOfOrderness,即在计算给定窗口的最终结果时允许元素延迟到被忽略之前的最长时间。延迟对应于的结果t - t_w,其中t元素的(事件时间)时间戳和t_w前一个水印的时间戳。如果lateness > 0那么该元素将被认为是较晚的元素,默认情况下,在为其相应窗口计算作业结果时将其忽略。

val stream: DataStream[MyEvent] = ...
val withTimestampsAndWatermarks = stream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[MyEvent](Time.seconds(10))( _.getCreationTime ))