Flink之watermark和allowedLateness区别

一、两者区别------写在最前面

watermark和allowedLateness区别

  • watermark 通过additional的时间戳来控制窗口激活的时间,主要是为了解决数据乱序到达的问题,
  • allowedLateness 用来控制窗口的销毁时间,解决窗口触发后数据迟到后的问题。
  • 在flink中我们经常使用watermark、allowedLateness 、 sideOutputLateData结合的方式处理数据保证窗口数据不丢失

二、watermark

watermark在Flink中也称为 水位线或水印,它为流式数据每隔一段时间打上一个标记,水位线maxOutOfOrderness(延迟时间)设置为2s意味着当100s的数据到来时flink只认为是98s之前的数据都到来了,触发窗口操作也是按98s来触发的,因此生产中需要调研或测试分析乱序数据的延迟分布特性(当然如果需求没有这方面的要求就不用这样了),如下图
Flink之watermark和allowedLateness区别_第1张图片
Flink之watermark和allowedLateness区别_第2张图片
waterMark相关的常用设置

    //给每一个stream追加eventTime时间特性,如果使用processingTime则不用设置
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    //为流式数据每隔一段时间打上一个标记,设置waterMark自动生成的时间间隔,不设置默认是200ms
    env.getConfig.setAutoWatermarkInterval(500)
    //处理乱序时间,eventTime取数据的timestamp,waterMark水位线延迟取1秒,例如时间戳5s水位线4s
    val waterMarkDataStream = dataStream.assignTimestampsAndWatermarks(
      //单位ms,waterMark水位线延迟取1秒,将数据提前一秒,199数据到来认为是198之前的全来了
      //后面再触发窗口操作时也以eventTime(和waterMark有关)为准,waterMark控制窗口的激活时间
      new BoundedOutOfOrdernessTimestampExtractor[Sensor](Time.milliseconds(1000)) {
      //设置EventTime,取数据的时间戳ms
        override def extractTimestamp(t: Sensor): Long = t.timestamp * 1000
      }
    )

三、allowedLateness允许延迟时间

allowedLateness只针对eventTime,因为processingTime不存在延时的情况。。

默认情况下,当watermark通过end-of-window激活window计算结束之后,再有之前的数据到达时,这些数据会被删除。
为了避免有些迟到的数据被删除,因此产生了allowedLateness,使用allowedLateness延迟销毁窗口,允许有一段时间(也是以event time来衡量)来等待之前的数据到达,以便再次处理这些数据。

//窗口分类:固定时间窗口、滑动时间窗口、滚动计数窗口,滑动计数窗口,window/timeWindow/countWindow
    //window方法必须在keyBy后才能用
    //allowedLateness窗口延迟关闭,控制窗口的销毁
    val result = waterMarkDataStream
      .map(data => (data.id, data.temperature))
      .keyBy(_._1)
      .timeWindow(Time.seconds(2)) 
      .allowedLateness(Time.seconds(2))
      .reduce((data1, data2) => (data1._1, data1._2.min(data2._2)))

四、窗口迟到数据

窗口watermark和allowedLateness之后依然迟到的流数据,也是通过.sideOutputLateData(outputTag)和result.getSideOutput(outputTag)的侧输出流方式输出的,拿到这一部分数据后用户可以自己处理,相比于spark的水印和数据延迟机制来说,flink的更加完善和易用

val outputTag = new OutputTag[(String, Double)]("side")
    val result = waterMarkDataStream
      .map(data => (data.id, data.temperature))
      .keyBy(_._1)
      .timeWindow(Time.seconds(2))
      .allowedLateness(Time.seconds(2))
      .sideOutputLateData(outputTag)
      .minBy(1)
    //.reduce((data1, data2) => (data1._1, data1._2.min(data2._2)))

    dataStream.print("in")
    val sideOutPutStream = result.getSideOutput(outputTag)
    sideOutPutStream.print("窗口watermark和allowedLateness之后依然迟到的流数据:")
    result.print("out")

    env.execute("TransformTest")

你可能感兴趣的:(flink)