Flink | EventTime 和Watermark


        通常情况下,由于网络原因或系统等外部因素,事件数据往往不能及时传输到Flink系统中,导致数据乱序到达或延迟到达,因此需要一种机制能够控制数据处理的过程和进度。水平线(watermarks)机制,它能够衡量数据处理进度,保证事件数据到达Flink系统,或者在乱序和延迟时,也能够像预期一样计算出正确并且连续的结果。Flink会将用读取进去系统的最新事件时间减去固定的时间间隔作为watermark,该时间间隔为用户外部配置的支持最大延迟到达的时间长度,也就是说不会有事件超过该间隔到达,否则就是迟到事件或异常事件。 

        当事件接入到Flink 系统时,会在Sources Operator 中根据当前最新事件时间产生Watermarks 时间戳记为X,进入到flink系统中的数据事件时间为Y,如果Y<X,则代表Watermark X时间戳之前的所有事件均已到达,同时Window的EndTime大于Watermark,则触发窗口计算结果并输出。从另外一个角度讲,如果想触发对Window内的数据元素的计算,就必须保证对所有进入到窗口的数据元素满足其事件时间Y>=X,否则窗口会继续等待Watermark大于窗口结束时间的条件满足。可以看出当有了Watermarks机制后,对基于事件时间的流数据处理会变得更加灵活,可以有效地处理数据乱序的问题。

    (1)顺序时间中的Watermarks

        如果数据的事件时间都是有序的,Watermark时间戳会随着数据的事件时间按顺序生成,当Watermark 时间大于Windows结束时间就会触发对Windows的数据计算,并创建另外一个新的Windows将事件时间Y<X的数据元素分配到新的Window中。事件按照原本的顺序进入Flink 系统,Watermark 跟随着事件时间之后生成,可以看出Watermarks 其实只是对Stream 简单地进行周期性地标记,并没有特别大的意义,也就是说在顺序事件的数据处理过程中,Watermarks并不能发挥太大的价值,反而会因为设定了超期时间而导致延迟输出计算结果。

    (2)乱序事件中的Watermarks

        现实情况下数据元素往往并不是按照其产生顺序接入到flink 系统中进行处理,而频繁出现乱序或迟到的情况,这种情况就需要使用Watermarks 来处理。

    (3)并行数据流中的Watermarks 

        Watermarks 在Source Operator 中生成,并且在每个Source Operator 的子Task中都会独立生成Watermark 。在Source Operator 的子任务中生成后就会更新该Task的Watermark,且会逐步更新下游算子中的Watermark水位线,随后一致保持在该并发之中,直到下一次Watermarks的生成,并对前面的Watermarks进行覆盖。如果多个Watermarks 同时更新一个算子Task 的当前事件时间,Flink 会选择最小的水位线来更新,当一个Window算子Task 中水位线大于了Window结束时间,就会立即触发窗口计算。

1、指定Timestamps与生成Watermarks

        如果使用Event Time 时间概念处理流式数据,除了在StreamExecutionEnvironment中指定TimeCharacteristic外,还需要在Flink程序中指定Event Time 时间戳在数据中的字段信息,在Flink 程序运行过程中会通过指定字段抽取对应的事件时间,该过程叫作Timestamps Assigning 。

Timestamps 指定完后,需要用户定义根据Timestamps 计算出Watermarks 的生成策略。目前Flink 支持两种方式指定Timestamps 和生成Watermarks ,一种是在DataStream Souce 算子接口的Source Function 中定义,另外一种是通过自定义Timestamp Assigner 和 Watermark Generator 生成。

    (1)在Source Function 中直接定义Timestamps 和 Watermarks 

        在DataStream Souce 算子中指定Event Timestamps,也就是说在数据进入到Flink 系统中就直接指定分配EventTime Timestamps . 用户需要复写SourceFuntion 接口中run()方法实现数据生成逻辑,同时需要调用SourceContext 的collectWithTimestamps() 方法生成EventTime 时间戳,调用emitWatermark() 方法生成Watermarks .

//创建数组数据集val input = List(("a",1L,1),("b",1L,1),("b",3L,1))//添加Datasource 数据源,实例化SourceFunction接口val source: DataStream[(String,Long,Int)] = env.addSource(  new SourceFunction[(String,Long,Int)](){    //复写run方法,调用SourceContext接口    override def run (ctx: SourceContext[(String,Long,Int)]): Unit = {      input.foreach(value =>{        //调用collectWithTimestamp 增加Event Time抽取             ctx.collectWithTimestamp(value,value._2)         //调用emitWatermark ,创建Watermark,最大延迟设定为1         ctx.emitWatermark(new Watermark(value._2-1))         })      //设定默认Watermark      ctx.emitWatermark(new Watermark(Long,MaxValue))    }    override def cancel (): Unit ={}  })

    (2)通过Flink 自带的Timestamp Assigner 指定Timestamp和生成Watermark 

        如果用户使用了Flink 已经定义的外部数据源连接器,就不能再实现SourceFunction接口来生成流式数据以及相应的Event Time 和Watermark ,这种情况下就需要借助Timestamp Assigner 来管理数据流中的Timestamp元素和Watermark 。Timestamp Assigner 应该在第一个时间相关的Operator 之前指定。如果用户已经在SourceFunction 中定义Timestamp 和 Watermarks 的生成逻辑,同时又使用了Timestamp Assigner , 此时Assigner 会覆盖Source Function 中定义的逻辑。

        Flink 将Watermarks根据生成形式分为两种类型,分别是Periodic Watermarks 和 Punctuated Watermarks 。Periodic Watermarks 是根据设定时间间隔周期性地生成Watermarks ,Punctuated Watermarks 是根据接入数据的数量生成。Flink 中两种生成Watermarks 的逻辑分别借助于AssignerWithPeriodicWatermarks 和AssignerWithPunctuatedWatermars

        在Flink 系统中实现了两种Periodic Watermark Assigner, 一种为升序,会将数据中的Timestamp 根据指定字段提取,并用当前的Timestamp 作为最新的Watermark,这种Timestamp Assigner 比较适合事件按顺序生成,没有乱序事件的情况;另外一种是通过设定固定时间间隔来指定Watermark 落后于Timestamp 的区间长度,也就是最长容忍迟到多长时间内的数据到达系统。

      1)使用Ascending Timestamp Assigner 指定Timestamps 和Watermarks

      2)   使用固定时延间隔的Timestamp Assigner 指定Timestamps 和 Watermarks。

       3)自定义Timestamp Assigner 和Watermark Generator.

博主的微信公众号,不定期发布技术文章,喜欢的可以关注一下哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值