flink 中的Watermark

在分布式的计算中,由于网络、服务器间的距离等问题,会导致数据顺序发生错乱,即在处理数据的时候,后发生的数据比先发生的数据更早到达,这对结果的计算会造成误差,这时候就需要引进时间语义。

在flink中,时间语义分为三种。

  1. Event Time:数据产生的时间
  2. Ingestion Time:数据进入flink的时间
  3. Processing Time:数据进入算子的时间

通常 Event Time  使用的更频繁。

 

以Event Time 为例:

在实际的场景中,如果数据顺序发生了错乱应该怎么处理呢?

最简单的办法就是等待,虽然后发生的数据先到达,但是我们可以等待先发生的数据到来,然后再进行处理,

问题是怎么等,等多久, 程序既要保证数据的准确性又要保持实时性。

为了解决这个问题,flink中引入了Watermark机制。

  • watermark 是专门用作处理乱序数据的,
  • watermark 用来表示小于某一时间戳的数据已经全部到达,不再继续进行等待。

watermark可以理解为设置了一个延迟时间,

设watermark时间为 t。所有数据中最大的时间按戳为 mt。每次数据到达,程序都会校验当前数据的时间戳和历史数据的最大时间戳。mt - t  可以认为所有小于mt - t 时间戳的数据已经全部到达,程序不再继续等待,对已有的数据进行处理。

假设设置watermark 为 2。时间窗口为5s  即每5s 处理一次数据。 假设有4个数据,分别发生在 1、3、5、7 s, 到达顺序是 1 5 7 3。

数据 5 到达时,可以认为所有 3 秒(5 - 2)前发生的数据都到达了,当数据 7 到达时,可认为前5s 的数据都到达了, 这时候满足了5s 的时间窗口,即对[ 0,5 ) 的一批数据进行处理。

最后 3s发生的数据到达的时候,窗口已经关闭,但是仍可以对 3 进行实时处理。

Watermark 的生成方式又分成两种:

  1. 周期性生成AssignerWithPeriodicWatermarks

周期性生成,是指程序根据一定的时间间隔,在数据流中插入一个watermark 对数据进行校验。这种模式下,默认Event Time 类型为200 毫秒

  1. 间断性生成,根据数据条数生成AssignerWithPunctuatedWatermarks

间断性生成,是指watermark没有固定的生成时间,根据到达的数据条数,插入到数据流中对数据进行校验。

 

Watermark在保证实时性的情况下,一定程度上保证了数据的准确性,为了进一步提高数据的准确性, flink中还有侧输出流保证数据的准确性,他允许程序处理迟到数据。

Watermark和侧输出流 测试代码:

这里以监听指定端口数据为例, 数据格式为 id,timestamp,value

case class Info(id:String, timestamp:Long, value:Double)
def main(args: Array[String]): Unit = {
    val environment = StreamExecutionEnvironment.createLocalEnvironment()
    // 为了方便观察效果,这里并行度设置为1
    environment.setParallelism(1)
    // 设置时间语义类型为事件时间
    environment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

    val socketStream = environment.socketTextStream("bigdata1", 7777)
    val value: DataStream[Info] = socketStream.map(data => {
      val strings = data.split(",")
      Info(strings(0), strings(1).toLong, strings(2).toDouble)
    })
        // 设置Watermark为3秒,允许数据迟到3s
      .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[Info](Time.seconds(3)) {
      override def extractTimestamp(element: Info): Long = element.timestamp * 1000L
    })
    val output: DataStream[Info] = value.
      keyBy(_.id)
	  // 设置滑动窗口大小为15s
      .timeWindow(Time.seconds(15))
	  // 设置晚来超过1分钟的数据为迟到数据
	  .allowedLateness(Time.minutes(1))
          // 处理迟到数据
      .sideOutputLateData(new OutputTag[Info]("late")).reduce((oldData,newData) => {
      Info(oldData.id, newData.timestamp, newData.value)
    })
    // 拿到侧输出流,输出迟到的数据    
    output.getSideOutput(new OutputTag[Info]("late")).print("late")
    // 输出正常到达的数据
    output.print("value")

    environment.execute("watermark demo")


  }

时间为005 秒的数据到达时,没有数据输出,意味着目前没有窗口关闭。

时间为008 数据到达时,此时,[0,5)  的窗口应当关闭,所以产生输出。上面的处理逻辑中,我们取最新的时间戳和最新的数值输出,所以这里 [0,5)窗口输出的是 003 秒时的数据。

此时,又有001 s的数据到达,仍然可以进行实时处理。

此时,068 秒的数据到达, 008 所在的窗口关闭,输出008的数据, 然后又有001的数据到达,此时 001 和 (068-003) 的时间间隔已经超过1分钟,

原来的流不在进行处理,而我们开启了侧输出流,允许对一分钟后到达的数据单独处理,所以这时候,输出的实际上是 late 侧输出流的数据

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FlinkWatermark是一种用于衡量Event Time进展的机制。它用于处理实时数据的乱序问题,并常与窗口结合使用来实现事件的有序处理。Watermark可以被理解为一种时间戳标记,表示在该标记之前的事件都已经到达,因此可以触发窗口计算。Watermark的生成可以通过实现WatermarkGenerator接口来实现,该接口包含了onEvent和onPeriodicEmit两个方法来生成Watermark。在onEvent方法,可以观察流事件数据,并在获取到带有Watermark信息的特殊事件元素时发出Watermark。而在onPeriodicEmit方法,可以根据需要周期性地发出Watermark。同时,在Flink,还可以通过WatermarkStrategy接口来定义Watermark的生成策略,该接口包含了createTimestampAssigner方法用于实例化一个可分配的时间戳生成器,以及createWatermarkGenerator方法用于实例化一个Watermark生成器。总之,WatermarkFlink起到了衡量事件时间进展和触发窗口计算的重要作用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Flink:Watermark](https://blog.csdn.net/qq_24325581/article/details/117515189)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [1分钟理解FlinkWatermark机制](https://blog.csdn.net/m0_68470434/article/details/126742410)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值