• Flink 之Window(窗口)


    关窗时间

    情况1:如果存在lateness延迟关窗设置,则
            
                关窗时间:最后一条数据event_time - watermark时间 - lateness时间
                窗口开始计算时间: 当时数据event_time - watermark时间
    
    如:latenes:为10分钟;窗口设置为:10分钟,步长为5;watermark:为1s
    
    则数据在10:50:00秒开始到来,则这条数据在【10:50:00 10:59:59)这个窗口都是有效,但是在10:50:52数据时刻开始窗口得计算

    如果数据是10:49:59得数据,它在
    【10:50:00 10:59:59)这个最后窗口关闭时都没有到来,就会输出到侧输出流

    知识点:

    注意 window () 方法必须在 keyBy 之后才能用
    
    window 类型 
        • 时间窗口(Time Window) 
            滚动时间窗口(tumbling window):将数据依据固定的窗口长度对数据进行切分 ;时间对齐,窗口长度固定,没有重叠
                适用场景:适合做 BI 统计等(做每个时间段的聚合计算)
            滑动时间窗口 (sliding window):滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口 长度和滑动间隔组成 ; 窗口长度固定,可以有重叠
                适用场景:对最近一个时间段内的统计(求某接口最近 5min 的失败率来决定是 否要报警)。
            会话窗口 (session window):由一系列事件组合一个指定时间长度的 timeout 间隙组成,也就是 一段时间没有接收到新数据就会生成新的窗口 ;时间无对齐
        • 计数窗口(Count Window) 
            滚动计数窗口 
            滑动计数窗口
            
    window function :定义了要对窗口中收集的数据做的计算操作 
        • 可以分为两类  
            增量聚合函数(incremental aggregation functions) : 每条数据到来就进行计算,保持一个简单的状态 ; ReduceFunction, AggregateFunction  
         全窗口函数(full window functions) : 先把窗口所有数据收集起来,等到计算的时候会遍历所有数据 ; ProcessWindowFunction Window其他Api .trigger() —— 触发器 : 定义 window 什么时候关闭,触发计算并输出结果 .evictor() —— 移除器 : 定义移除某些数据的逻辑 .allowedLateness() —— 允许处理迟到的数据 .sideOutputLateData() —— 将迟到的数据放入侧输出流 .getSideOutput() —— 获取侧输出流

    1、代码案例1

    package window
    
    import com.yangwj.api.SensorReading
    import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
    import org.apache.flink.streaming.api.scala._
    import org.apache.flink.streaming.api.windowing.time.Time
    /**
     * @author yangwj
     * @date 2021/1/7 21:45
     * @version 1.0
     */
    object WindowTest {
      /**
       * 窗口:分为时间窗口和计数窗口
       * @param args
       */
      def main(args: Array[String]): Unit = {
        val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
        val inputFile:String = "G:\Java\Flink\guigu\flink\src\main\resources\sensor.txt"
        val input: DataStream[String] = env.readTextFile(inputFile)
    
        val dataStream = input.map(data => {
          val arr: Array[String] = data.split(",")
          SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
        })
    
        dataStream
          .map(data => (data.id,data.temperature))
          .keyBy(_._1) //按照二元组的第一个元素分组
         // .window(TumblingEventTimeWindows.of(Time.seconds(15))) //定义滚动时间窗口
    //      .window(SlidingEventTimeWindows.of(Time.minutes(5),Time.seconds(5)))//滑动窗口
    //      .window(EventTimeSessionWindows.withGap(Time.seconds(5)))// 会话窗口
          .timeWindow(Time.seconds(15))//定义滚动时间窗口
    //      .timeWindow(Time.minutes(5),Time.seconds(5))//滑动窗口
          //.countWindow(5)//计数窗口
          .reduce((r1,r2) => (r1._1,r1._2.min(r2._2))).print("test")
        
        env.execute(" window test")
      }
    }

    2、代码案例2

    package window
    
    import com.yangwj.api.SensorReading
    import org.apache.flink.streaming.api.functions.source.SourceFunction
    import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment, _}
    import org.apache.flink.streaming.api.windowing.time.Time
    
    import scala.util.Random
    
    /**
     * @author yangwj
     * @date 2021/1/7 21:45
     * @version 1.0
     */
    object WindowTest1 {
      /**
       * 窗口:分为时间窗口和计数窗口
       * @param args
       */
      def main(args: Array[String]): Unit = {
        val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    
        val dataStream: DataStream[SensorReading] = env.addSource(new MySensorSource)
        //每15秒统计一次温度最小值
        val value: DataStream[(String, Double, Long)] = dataStream
          .map(data => (data.id, data.temperature, data.timestamp))
          .keyBy(_._1) //按照二元组的第一个元素分组
          // .window(TumblingEventTimeWindows.of(Time.seconds(15))) //定义滚动时间窗口
          //      .window(SlidingEventTimeWindows.of(Time.minutes(5),Time.seconds(5)))//滑动窗口
          //      .window(EventTimeSessionWindows.withGap(Time.seconds(5)))// 会话窗口
          .timeWindow(Time.seconds(15)) //定义滚动时间窗口
          //      .timeWindow(Time.minutes(5),Time.seconds(5))//滑动窗口
          //.countWindow(5)//计数窗口
          //      .minBy(1)
          .reduce((curs, newd) => (curs._1, curs._2.min(newd._2), newd._3))
    
        value.print("windows")
        env.execute("reduce test")
    
      }
    }
    //自定义数据源
    class MySensorSource extends SourceFunction[SensorReading]{
    
      //定义一个标识位,用来表示数据源是否正常运行发出数据
      var running :Boolean = true
      //sourceContext 发送数据
      override def run(sourceContext: SourceFunction.SourceContext[SensorReading]): Unit = {
        //定义无线循环,不断产生数据,除非被cancel
        val rand = new Random()
        var curTemp= 1.to(4).map(i => ("sensor" + i, rand.nextDouble() * 100))
    
        while (running){
          curTemp = curTemp.map(data =>(data._1,data._2+rand.nextGaussian()))
    
          val curTime = System.currentTimeMillis()
          println("输入值:"+curTemp+",时间为:"+curTime)
          curTemp.foreach(data => sourceContext.collect(SensorReading(data._1,curTime,data._2)))
          Thread.sleep(3000)
        }
      }
    
      override def cancel(): Unit = false
    }
  • 相关阅读:
    .NET Core MVC 发布到IIS配置文件
    TP5导出scv格式数据,支持百万数据
    PHP导出Excel表格及设置表格样式
    如何查看Linux的内存使用状况
    tp5.1 + think-queue + supervisor
    java使用HAMC签名加密调用第三方接口
    记录:SpringBoot多个配置文件激活一个
    通过反射获取注解
    (function(){})(jQuery)与$.fn的使用
    IDEA配置203底座之lib配置
  • 原文地址:https://www.cnblogs.com/ywjfx/p/14254311.html
Copyright © 2020-2023  润新知