Flink watermark

在Flink中支持三种不同的时间概念:处理时间(processing time)、事件时间(event time)、摄取时间(Ingestion time)。

而水印是衡量event time 进展的一种机制,它通常基于事件时间数据属性产生,水印作为数据流的一部分流动并带有时间戳t,代表该时间点以前的数据都已经到达。

watermark主要是用于处理乱序事件。而正确的处理乱序事件,通常用watermark机制结合window来实现。

流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的。虽然大部分情况下,流到operator的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络、背压等原因,导致乱序的产生(out-of-order或者说late element)。

但是对于late element,我们又不能无限期的等下去,必须要有个机制来保证一个特定的时间后,必须触发window去进行计算了。这个特别的机制,就是watermark。

为了处理事件时间,Flink需要知道事件的时间戳,这意味着流中的每个元素都需要分配其事件时间戳。这通常通过从元素中的某个字段访问/提取时间戳来完成。

时间戳分配与生成水印密切相关,水印告诉系统事件时间的进展。

有两种方法可以分配时间戳并生成水印:

  1. 直接在数据流源中
  2. 通过时间戳分配器/水印生成器:在Flink中,时间戳分配器还定义要发出的水印

流源可以直接为它们生成的元素分配时间戳,它们也可以发出水印。完成此操作后,不需要时间戳分配器。请注意,如果使用时间戳分配器,则将覆盖源提供的任何时间戳和水印。

要直接为源中的元素分配时间戳,源必须使用该collectWithTimestamp(...) 方法SourceContext。要生成水印,源必须调用该emitWatermark(Watermark)函数。

时间戳分配器获取流并生成带有带时间戳元素和水印的新流。如果原始流已经有时间戳和/或水印,则时间戳分配器会覆盖它们。

使用周期性水印

AssignerWithPeriodicWatermarks 分配时间戳并定期生成水印(可能取决于流元素,或纯粹基于处理时间)。

生成水印的间隔(每n毫秒)通过定义 ExecutionConfig.setAutoWatermarkInterval(...)getCurrentWatermark()每次调用分配器的方法,如果返回的水印非空并且大于先前的水印,则将发出新的水印。

 

带有标识的水印

要在某个事件表明可能生成新水印时生成水印,请使用 AssignerWithPunctuatedWatermarks。对于此类,Flink将首先调用该extractTimestamp(...)方法为元素分配时间戳,然后立即调用该checkAndGetNextWatermark(...)元素上的 方法。

checkAndGetNextWatermark(...)方法传递方法中分配的时间戳extractTimestamp(...) ,并可以决定是否要生成水印。每当该checkAndGetNextWatermark(...) 方法返回非空水印,并且该水印大于最新的先前水印时,将发出该新水印。

Flink提供抽象,允许程序员分配他们自己的时间戳并发出他们自己的水印。更具体地说,可以通过实现其中一个AssignerWithPeriodicWatermarksAssignerWithPunctuatedWatermarks接口来实现,具体取决于用例。简而言之,第一个将定期发出水印,而第二个基于传入记录的某些属性,例如,只要在流中遇到特殊元素。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值