flink workmark+window超時后处理 allowedLateness、sideOutputLateData

背景:

在flink实际开发过程种:
一般我们处理日志数据时候,我们会指定event time 作为我的时间作为程序内窗口函数内时间基准。

问题:但是由于部分机器节点存在网络延迟等原因,并且kafka 消息队列本身也不能保证全局消息的一致性的问题。导致时间乱序并且延迟问题。为了解决这种问题flink 提供三种方式来改变这个问题。
分别是watermark allowedLateness() 和sideOutputLateDate() 三种机制来保证获取并处理数据。

三种结合使用例子:

import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows
import org.apache.flink.streaming.api.windowing.time.Time
 
object demo1 {
  def main(args: Array[String]): Unit = {
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    //从调用开始给env创建的每一个streamin 追加时间特征
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime )
    val inputStream: DataStream[String] = env.socketTextStream("hadoop102",7777)
    val outputTag = new OutputTag[SensorReading]("side")
    val dataStream = inputStream
      .map(data => {
        val dataArray = data.split(",")
        SensorReading(dataArray(0).trim, dataArray(1).trim.toLong, dataArray(2).trim.toDouble)
      }).
      //给水印一个初始化的延迟时间
      assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(2)) {
      override def extractTimestamp(element: SensorReading): Long = {
        element.timestamp*1000 
        //我的测试时间戳是s,flink要求ms
      }
    })
    val minStream: DataStream[SensorReading] = dataStream.keyBy(_.id)
      //  .window( SlidingEventTimeWindows.of(Time.seconds(10),Time.seconds(2)))
      //初始化开窗时间间隔为10秒
      .timeWindow(Time.seconds(10))
      .allowedLateness(Time.seconds(4))
      .sideOutputLateData(outputTag)**
      .minBy("temperature")
    dataStream.print("data")
    minStream.print("min")
    minStream.getSideOutput(outputTag).print("slide")
    env.execute("demo1")
  }
}
case class SensorReading(id: String, timestamp: Long, temperature: Double)

水平线watermark

由提我们设置窗口时间为10秒,水位线设置2 秒 所以在窗口时间【0 ,10) 前闭后开的时间窗口内允许时间晚到2秒钟(即实际情况是【0,12)的时间窗口内找出符合【0,10)时间的数据)

迟到数据allowedLateness

在此例子中迟到数据我们设计的可以允许数据迟到4秒钟,即实际效果为在水印的12秒的基础上增加了4秒去关闭窗口。(即实际情况是【0,16)的时间窗口内找出符合【0,10)时间的数据 ,但和水印不同的是这个只是对上个窗口数据【0,12)中的数据进行修正多输出一条(待验证)

侧输出流sideOutputLateData

兜底保证,即窗口关闭之后,把数据输出到侧输出流中,之后卡到late 的数据可以进行和之前的数据进行合并。

测试代码 (测试数据为 时间戳和温度) 注:加粗部分为数据晚到的 其它时间都是按照正常时间无延迟到达。
sensor_1, 1547718120,20
sensor_1, 1547718130,10
sensor_1, 1547718131,9
sensor_1, 1547718132,8
sensor_1, 1547718120,9
sensor_1, 1547718135,5
sensor_1, 1547718120,9
sensor_1, 1547718136,4
sensor_1, 1547718120,9

打印结果为

data> SensorReading(sensor_1,1547718120,20.0)
data> SensorReading(sensor_1,1547718130,10.0)
data> SensorReading(sensor_1,1547718131,9.0)
data> SensorReading(sensor_1,1547718132,8.0)
min> SensorReading(sensor_1,1547718120,20.0)
data> SensorReading(sensor_1,1547718120,9.0)
min> SensorReading(sensor_1,1547718120,9.0)
data> SensorReading(sensor_1,1547718135,5.0)
data> SensorReading(sensor_1,1547718120,9.0)
min> SensorReading(sensor_1,1547718120,9.0)
data> SensorReading(sensor_1,1547718136,4.0)
data> SensorReading(sensor_1,1547718120,9.0)
slide> SensorReading(sensor_1,1547718120,9.0)

分析:
1、时间开始时间为1547718120,所以第一个窗口是【20-30)
但时间关闭时间为【20,32)所以在【20,32) 只
SensorReading(sensor_1,1547718120,20.0)
符合要求输出

2、然后数据SensorReading(sensor_1,1547718120,20.0)延迟到来(在35秒之前)
此时allowlateness【20,36)起作用,认为这条数据也是延迟数据,对原先算出的最小值20进行修正,最后算出min=9.0

3、所以输入35的时候,这条数据,会进入到第二个窗口,同时第一个窗口还没有彻底关闭,所以再次输入 SensorReading(sensor_1,1547718120,9.0),仍然会进入到【20-30)的窗口,并在此计算最小值

4、输入SensorReading(sensor_1,1547718136,4.0),窗口彻底关闭,再次输入 SensorReading(sensor_1,1547718120,9.0),不再对第一个窗口min进行修正,直接把数据放到测输入流,以后所有的【20-30)的数据在输入都会全部放到侧输出流

总结:
1、窗口window 的作用是为了周期性的获取数据

2、watermark的作用是防止数据出现乱序(经常),事件时间内获取不到指定的全部数据,而做的一种保险方法,

3、allowLateNess,是将窗口关闭时间再延迟一段时间,

思考?这里的allowLateNess 感觉就好像window变大了,那么为什么不直接把window设置大一点呢?或者把watermark加大点 (感觉allowLateNess 更像一种修正算亡羊补牢,水印要求时间准确算正常计算逻辑)todo 验证

4、sideOutPut是最后兜底操作,所有过期延迟数据,指定窗口已经彻底关闭了,就会把数据放到侧输出流

参考:https://blog.csdn.net/cclovezbf/article/details/102691262

猜你喜欢

转载自blog.csdn.net/weixin_40809627/article/details/106985347