【Flink】窗口起始点



EventTime窗口的起始时间是以读取的第一条事件时间戳为基准,比方说
第一条时间时间是: 2020-11-11 14:43:11,
滚动时间间隔15s,
watermark间隔是3s,
偏移量是0,
延迟时间是1分钟后放入侧输出流

那么起始时间就是:

1605076991*1000 - (1605076991*1000 - 0 + 15*1000)% (15*1000)

1605076991000 - 11000  :减去11s 

1605076980

也就是说窗口的起始时间是从 :2020-11-11 14:43:00 开始第一个窗口,那么窗口按照15s一个窗口进行切分,
   
   
      窗口                    value
1)[14:43:00~14:43:15)         2
2)[14:43:15~14:43:30)         3 
3)[14:43:30~14:43:45)         4 5 6
4)[14:43:45~14:44:00)         7 
5)[14:44:00~14:44:15)         8 9  
6) [14:44:15~ 14:44:30)        10 11 12 13 
...





	测试数据            对应时间          watermark       状态
                                          
s1,1605076991,2         14:43:11          14:43:08        第一条数据进来,开启第一个窗口
s1,1605076998,3         14:43:18          14:43:15        wm是15,第一个窗口关闭,最小值是2
s1,1605077010,4         14:43:30          14:43:27        
s1,1605077011,5         14:43:31          14:43:28         
s1,1605077019,6         14:43:39          14:43:36        wm是36,第二个窗口关闭,最小值是3
s1,1605077025,7         14:43:45          14:43:42         
s1,1605077040,8         14:44:00          14:43:57        第三个窗口关闭,最小值是4
s1,1605077054,9         14:44:14          14:44:11        第四个窗口关闭,最小值是7
s1,1605077055,10        14:44:15          14:44:12
s1,1605077056,11        14:44:16          14:44:13
s1,1605077057,12        14:44:17          14:44:14
s1,1605077058,13        14:44:18          14:44:15        第五个窗口关闭,最小值是8         
s1,1605076990,1         14:43:10          14:43:07        进入侧输出流
s1,1605081170,100       15:52:50          15:52:43        因为时间差比较大,之前所有的窗口全部关闭,最小值是10
s1,1605076989,11        14:43:09          14:43:06        进入侧输出流


代码如下:


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

/**
 * FileName: WindowT
 * Author:   ***********
 * Date:     2020/11/11 11:14
 * Description: 
 */
object WindowT {
  def main(args: Array[String]): Unit = {

    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    //设置周期性插入watermark,默认时间间隔是200s,也可以通过下面设置时间间隔
    env.getConfig.setAutoWatermarkInterval(50)

    //读取socket流数据
    val inputStream: DataStream[String] = env.socketTextStream("node01", 7777)
    //转换数据 并提取时间戳
    val dataStream: DataStream[SensorReading] = inputStream.map(data => {
      val arr: Array[String] = data.split(",")
      SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
    })

      /**
       * 提取时间戳的方式有两种,一种是这种升序时间戳,另外一种是乱序的时间戳
       */
      // 1.方式1 提取升序的时间戳(毫秒)
      //.assignAscendingTimestamps(_.timestamp * 1000L)
      // 2.方式2 通过周期性提取有界的乱序时间戳,也就是乱序时间戳
      // 给了3s的watermark
      .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(3)) {
        override def extractTimestamp(element: SensorReading): Long = element.timestamp * 1000L
      })

    //侧输出流
    val latetag = new OutputTag[(String, Double, Long)]("late")

    //每15秒统计一次,窗口内各传感器所有温度的最小值,以及最新的时间戳
    val resultStream: DataStream[(String, Double, Long)] = dataStream.map(data => (data.id, data.temperature, data.timestamp))
      .keyBy(0)
      //滚动窗口 15s
      .timeWindow(Time.seconds(15))
      //为保证延迟数据不丢失,设置处理迟到数据以及从侧输出流获取数据
      //延迟1分钟
      .allowedLateness(Time.minutes(1))
      //获取测输出流
      .sideOutputLateData(latetag)
      .reduce((curData, newData) => (curData._1, curData._2.min(newData._2), newData._3))

    // 打印侧输出流
    resultStream.getSideOutput(latetag).print("late")
    //打印结果
    resultStream.print("result")

    //执行程序
    env.execute("window demo 2")
  }
}



下面看timeWindow源码

 

 

 

 

 

### 渐进窗口聚合的概念 在 Flink SQL 中,渐进窗口聚合是一种基于时间或计数的连续计算方式。它允许用户在一个持续的时间范围内对数据进行分组并执行聚合操作。这种机制特别适合于实时数据分析场景,在这些场景中,数据流通常是无界的,并且需要动态更新结果。 通过 Windowing TVFs(窗口表值函数),可以灵活地定义不同类型的窗口以及相应的聚合逻辑[^1]。例如,可以通过 `TUMBLE` 或 `HOP` 定义固定大小的时间窗口或者滑动窗口,并结合常见的聚合函数如 `SUM()`、`AVG()` 等完成计算[^2]。 --- ### 示例教程:Flink SQL 逐步窗口聚合 #### 数据准备 假设我们有一个名为 `clicks` 的输入表,记录用户的击事件及其发生时间戳: | user_id | url | event_time | |---------|-----------|--------------------| | Alice | page_01 | 2023-09-01 10:00:00 | | Bob | page_02 | 2023-09-01 10:05:00 | | Alice | page_03 | 2023-09-01 10:10:00 | 该表结构如下: ```sql CREATE TABLE clicks ( user_id STRING, url STRING, event_time TIMESTAMP(3), WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND -- 设置水印延迟 ) WITH (...); ``` --- #### 使用 TUMBLE 进行渐进窗口聚合 下面是一个简单的例子,展示如何按每分钟统计每个用户的击次数: ```sql SELECT user_id, TUMBLE_START(event_time, INTERVAL '1' MINUTE) AS window_start, COUNT(*) AS click_count FROM clicks GROUP BY user_id, TUMBLE(event_time, INTERVAL '1' MINUTE); -- 按照一分钟滚动窗口分组 ``` 解释: - `TUMBLE(event_time, INTERVAL '1' MINUTE)` 创建了一个长度为 1 分钟的翻滚窗口。 - `TUMBLE_START(...)` 返回当前窗口的起始时间。 - 聚合函数 `COUNT(*)` 统计了每个窗口内的击总数。 --- #### 使用 HOP 实现滑动窗口聚合 如果希望使用滑动窗口,则可以用 `HOP` 函数替代 `TUMBLE`。以下是按照每两分钟滑动一次,每次一分钟后统计数据的例子: ```sql SELECT user_id, HOP_START(event_time, INTERVAL '1' MINUTE, INTERVAL '2' MINUTE) AS window_start, HOP_END(event_time, INTERVAL '1' MINUTE, INTERVAL '2' MINUTE) AS window_end, AVG(url_length) AS avg_url_length FROM clicks GROUP BY user_id, HOP(event_time, INTERVAL '1' MINUTE, INTERVAL '2' MINUTE); -- 滑动窗口参数 (步长=1min, 总窗宽=2min) ``` 这里引入了新的概念: - `HOP_START(...)` 表示滑动窗口的开始时间。 - `HOP_END(...)` 则表示结束时间。 - 假设我们在原始表中增加了一列 `url_length` 来存储 URL 长度,那么还可以进一步扩展到其他复杂指标的计算。 --- #### 结果输出与优化建议 最终的结果将以表格形式呈现给下游消费者。为了提高性能和可维护性,请注意以下几: 1. **合理设置 Watermark**:确保迟到的数据不会显著影响整体吞吐量。 2. **选择合适的窗口类型**:对于低频次业务推荐采用较大的窗口间隔;而对于高频交易则需缩短周期以便快速响应变化趋势[^2]。 3. **监控资源消耗情况**:长时间运行的任务可能累积大量状态信息,定期清理过期数据有助于减轻内存压力。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值