【Flink】关于Time和Window的基本知识点


引言

在这里插入图片描述
Flink有四大基石:CheckpointStateTimeWindow
这篇文章主要说一下TimeWindow
 

Time

概述

在这里插入图片描述
Event Time —— 时间创建的时间,通常由事件中的时间戳描述。比如采集日志数据中,每一个日志都会记录自己的生成时间,Flink通过时间戳分配器访问时间时间戳。
Ingestion Time —— 数据进入Flink的时间。
Processing Time —— 每一个执行基于时间操作的算子的本地系统时间,与机器相关,默认的时间属性就是Processing Time。

如果要统计1min内的故障日志个数,Event Time更有意义,因为要根据日志的生成时间进行统计。
 

Window

TimeWindow
滚动窗口 | Tumbling Windows

滚动窗口分配程序会将每个元素分配到一个指定窗口大小的窗口中,滚动窗口大小固定且不重叠
例如,如果指定了一个大小为5分钟的滚动窗口,那么就会计算当前窗口并每隔五分钟启动一个新的窗口,如下图所示
在这里插入图片描述
所以,滚动窗口的特点时间对齐窗口长度固定没有重叠。一般适用于做每个时间段的聚合计算,比如BI统计等。
 

滑动窗口 | Sliding Windows

滑动窗口分配程序会将元素分配到固定长度的窗口中,与滚动窗口类似,窗口的大小由窗口大小参数来配置,另一个附加的滑动窗口参数控制滑动窗口启动的频率。因此,如果滑动窗口小于窗口大小,则滑动窗口可以重叠。在这种情况下,元素被分配给多个窗口。
例如,有一个10分钟大小的窗口和5分钟的滑动,那么每隔5分钟就会出现一个包含最近10分钟到达的事件的窗口,如下图所示
在这里插入图片描述

会话窗口 | Session Windows

会话窗口分配器会按session活动对元素进行分组,会话窗口不会重叠,有没有固定的开始时间和结束时间。当会话窗口在一段时间内没有接收到元素时,也即非活动间隔产生,会话窗口就会关闭。一个session窗口由一个session间隔来配置,这个session间隔定义了非活跃周期的长度,当这个非活跃周期产生,那么当前的session将关闭并且后续的元素将被分配到新的session窗口中去。
在这里插入图片描述
 

CountWindow

CountWindow根据窗口中相同key元素的数量来触发执行,执行时只计算元素数量达到窗口大小的key对应的结果。
注意:CountWindow的window_size指的是相同Key的元素的个数,不是输入的所有元素的总数。
 

实例
CountWindow && TimeWindow
import org.apache.flink.api.java.tuple.Tuple
import org.apache.flink.streaming.api.scala.{DataStream, KeyedStream, StreamExecutionEnvironment, WindowedStream}
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.{GlobalWindow, TimeWindow}

object WordCountFromWindows {
  def main(args: Array[String]): Unit = {
    /**
     * 1.获取执行环境
     * 2.创建socketSource
     * 3.对获取到的数据进行切割和keyBy聚合操作
     * 4.引入窗口(timeWindow和CountWindow的滚动and滑动)
     * 5.对引入窗口数据进行聚合操作
     * 6.打印或写入文件
     * 7.执行环境
     */
    // 1.获取执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment

    // 2.创建socketSource
    val socketDataStream: DataStream[String] = env.socketTextStream("node01", 9999)

    // 3.对获取到的数据进行切割和keyBy聚合操作
    import org.apache.flink.api.scala._

    val splitDataStream: DataStream[String] = socketDataStream.flatMap(item => item.split(" "))
    val mapDataStream: DataStream[(String, Int)] = splitDataStream.map(ele => (ele, 1))
    val groupedDataStream: KeyedStream[(String, Int), Tuple] = mapDataStream.keyBy(0)

    // 4.引入窗口
      // 4.1 CountWindow
        // 4.1 滚动窗口
        val countWindowTumbling: WindowedStream[(String, Int), Tuple, GlobalWindow] = groupedDataStream.countWindow(5)
        // 4.2 滑动窗口
        val countWindowSliding: WindowedStream[(String, Int), Tuple, GlobalWindow] = groupedDataStream.countWindow(5, 3)
    
      // 4.2 TimeWindow
        // 4.2.1 滚动窗口
        val timeWindowTumbling: WindowedStream[(String, Int), Tuple, TimeWindow] = groupedDataStream.timeWindow(Time.seconds(5))
        // 4.2.2 滑动窗口
        val timeWindowSliding: WindowedStream[(String, Int), Tuple, TimeWindow] = groupedDataStream.timeWindow(Time.seconds(10), Time.seconds(5))

    // 5.对引入的窗口数据进行聚合操作
    val sumDataStream: DataStream[(String, Int)] = countWindowTumbling.sum(1)
    // 6.打印或写入文件
    sumDataStream.print()
    
    // 7.运行执行环境
    env.execute("WordCountFromWindows")
  }
}

 

WindowReduce
package cn.itcast.streaming

import org.apache.flink.api.java.tuple.Tuple
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
import org.apache.flink.streaming.api.windowing.windows.TimeWindow

object WindowReduceDemo {
  def main(args: Array[String]): Unit = {
    /**
     * 1.创建执行环境
     * 2.获取socket数据源
     * 3.划分窗口
     * 4.reduce操作
     * 5.输出数据
     */
    // 1.创建执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment

    // 2.获取socket数据源
    val socketDataStream: DataStream[String] = env.socketTextStream("node01", 9999)

    // 3.对数据切割聚合
    val groupedDataStream: KeyedStream[(String, Int), Tuple] = socketDataStream.flatMap(item => item.split(" ")).map(ele => (ele, 1)).keyBy(0)

    // 4.引入窗口
    val windowedStream: WindowedStream[(String, Int), Tuple, TimeWindow] = groupedDataStream.timeWindow(Time.seconds(5))

    // 5.reduce操作
    val reduceDataStream: DataStream[(String, Int)] = windowedStream.reduce((x1, x2) => (x1._1, x1._2 + x2._2))

    reduceDataStream.print()

    env.execute("WindowReduceDemo")
  }
}

 

WindowApply
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.scala.function.WindowFunction
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector


object WindowApplyDemo {
  def main(args: Array[String]): Unit = {
    /**
     * 1)获取流处理运行环境
     * 2)构建socket流数据源,并指定IP地址和端口号
     * 3)对接收到的数据转换成单词元组
     * 4)使用 keyBy 进行分流(分组)
     * 5)使用 timeWinodw 指定窗口的长度(每3秒计算一次)
     * 6)实现一个WindowFunction匿名内部类
     *    a.apply方法中实现聚合计算
     *    b.使用Collector.collect收集数据
     * 7)打印输出
     * 8)启动执行
     */
    // 1.获取流处理运行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment

    // 2.构建socket流数据源,并指定IP地址和端口号
    val socketDataStream: DataStream[String] = env.socketTextStream("node01", 9999)

    // 3.对接收到的数据转换成单词元组
    val mapDataStream: DataStream[(String, Int)] = socketDataStream.flatMap(_.split(" ")).map((_, 1))

    // 4.使用 keyBy 进行分流(分组)
    val keyedStream: KeyedStream[(String, Int), String] = mapDataStream.keyBy(_._1)

    // 5.使用 timeWinodw 指定窗口的长度(每3秒计算一次)
    val windowedStream: WindowedStream[(String, Int), String, TimeWindow] = keyedStream.timeWindow(Time.seconds(5))

    // 6.实现一个WindowFunction匿名内部类
    val reduceStream: DataStream[(String, Int)] = windowedStream.apply(new WindowFunction[(String, Int), (String, Int), String, TimeWindow] {
      override def apply(key: String, window: TimeWindow, input: Iterable[(String, Int)], out: Collector[(String, Int)]): Unit = {
        val tuple: (String, Int) = input.reduce((t1, t2) => {
          (t1._1, t1._2 + t2._2)
        })
        out.collect(tuple)
      }
    })

    // 7.输出数据
    reduceStream.print()

    //8.启动执行环境
    env.execute("WindowApplyDemo")
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值