Flink中解决乱序数据丢失问题Watermark(scala版)

将已经到的所有数据时间戳最大的时间再减去一个固定的延迟时间,做为关闭窗口的依据,如:某时刻已经来的数据时间最大的为5,延迟时间为2,那么该关闭的窗口就为[0,3),这里时间是从零时刻开始的。
1.无乱序数据,防止数据漏掉的方法
.assignAscendingTimestamps(_.timestamp * 1000L) // 升序数据提取时间戳 , 该方法用于没有乱序数据的情况下
2.有乱序情况下:
    a.每来一个数据生产一个设置最大延迟时间
    b.根据最大乱序来周期性生产设置最大延迟时间
1).尽可能将最大乱序程度作为assignTimestampsAndWatermarks的值,这样可以保证数据不丢失,如果设置过大会影响实时性
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[ApacheLogEvent](Time.seconds(1)) { //最大乱序程度,更加要处理的数据来查看
  override def extractTimestamp(element: ApacheLogEvent): Long = element.timestamp
}

2).通过设置窗口关闭时间来保证数据不丢失,在开窗之前设置allowedLateness

方法为:

//延迟窗口关闭时间来处理乱序数据,窗口登一分钟再关闭
.allowedLateness(Time.minutes(1))

 3).如果了为实时性和效率考虑,上述两种方法很难保证数据不丢失,就可以将迟到的数据放在测输出流中,方法为

.sideOutputLateData(new OutputTag[ApacheLogEvent]("late"))

 数据将会存放在late测输出流中,获取方法为:

val latevalue = aggStream.getSideOutput(new OutputTag[ApacheLogEvent]("late"))

 

案例:

样例类:

case class SensoreReding(id: String , timestamp: Long , temperature: Double)

核心代码:

package com.guqunyong.window


import com.guqunyong.APITest.SensoreReding
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.time.Time


/**
* 处理数据乱序问题
* @author shkstart
* @create 2021-07-24 11:15
*/
object WindowTest {
  def main(args: Array[String]): Unit = {
    //创建环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    env.getConfig.setAutoWatermarkInterval(50)
    //读取数据
    val value = env.socketTextStream("localhost", 7777)
    val dataStream = value.map(
      data => {
        val fields = data.split(",")
        SensoreReding(fields(0), fields((1)).toLong, fields(2).toDouble)
      }
    )
    //  .assignAscendingTimestamps(_.timestamp * 1000L)   //升序数据提取时间戳,该方法用于没有乱序数据的情况下
      .assignTimestampsAndWatermarks(
        new BoundedOutOfOrdernessTimestampExtractor[SensoreReding](Time.seconds(3)) {//最大乱序,即为最大延迟时间设置为3s
          override def extractTimestamp(element: SensoreReding): Long = element.timestamp * 1000L
        }
      )



    //每15秒统计一次,窗口内各传感器所有温度的最小值
    val resultStream = dataStream
      .map(data => (data.id,data.temperature,data.timestamp))
      .keyBy(_._1)
      .timeWindow(Time.seconds(15))
      .allowedLateness(Time.minutes(1))  //处理迟到1分钟的数据
      .sideOutputLateData(
        //将将漏掉的数据放到测输出流中处理
          new OutputTag[(String, Double, Long)]("late")
      )
      //.minBy(1)
      .reduce(
        (curRes,newData) => (curRes._1,curRes._2.min(newData._2),newData._3)
      )


    resultStream.print()
    //执行
    env.execute("window test")
  }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Flink 乱序问题指的是事件流在处理过程不按照时间顺序到达。为了解决乱序问题,可以考虑以下几种方法: 1. Watermark 和 Event Time:使用 Event Time 概念来处理事件流。Flink 提供了 Watermark 机制来标记事件的事件时间,通过设置适当的 Watermark 值,可以告知 Flink 在某个时间点之后不再有新的事件到达。这样可以在处理事件时,根据事件时间来进行排序和处理。 2. 乱序窗口(Out-of-Order Windows):Flink 提供了乱序窗口的支持,可以按照事件的事件时间和乱序时间进行窗口的划分和计算。通过设置窗口的允许乱序时间,可以在一定程度上容忍事件的乱序到达。 3. 重排序缓冲区(Reordering Buffer):在某些场景下,可以使用重排序缓冲区来缓冲乱序的事件,并根据事件时间进行排序后再进行处理。这种方式需要维护一个缓冲区,并设置合适的缓冲时间窗口。 4. 侧输出流(Side Outputs):通过将乱序事件发送到侧输出流,可以将乱序事件和正常顺序的事件分开处理。这样可以针对乱序事件使用不同的处理逻辑。 5. 使用状态(State):在 Flink 使用状态来保存事件的状态信息,可以在乱序事件到达时,根据事件的事件时间和当前状态进行排序和处理。 以上方法可以根据具体的业务需求和场景选择适合的解决方案。在实际应用,可能需要结合多种方法来处理乱序问题

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GQYOneWater

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值