Flink学习笔记(九):flink窗口介绍

一、概述

在日常生活场景中,我们经常需要获取某一个事件段的数据,如上文所说,希望统计在10点-11点事件段数据的具体情况,那么如何进行处理呢?

如有看过前文(Flink学习笔记(七):flink聚合函数)的小伙伴们可能会记得有一个countWindow,这就是flink给我们提供的算子(窗口,window),使用窗口方法我们可以将数据流分成一个个窗口,然后对窗口内的数据进行处理。

我们先看下flink官网对窗口的描述

windows是处理无限流的核心。 Windows将流分成有限大小的“存储桶”,我们可以在其上应用计算。 本文档重点介绍如何在Flink中执行窗口化,以及程序员如何从其提供的功能中获得最大收益。

窗口式Flink程序的一般结构如下所示。 第一个片段是指键控流,而第二个片段是指非键控流。 可以看到,唯一的区别是对键控流的keyBy(…)调用和对非键控流的window(…)变为windowAll(…)。

Keyed Windows

stream
       .keyBy(...)               <-  keyed versus non-keyed windows
       .window(...)              <-  required: "assigner"
      [.trigger(...)]            <-  optional: "trigger" (else default trigger)
      [.evictor(...)]            <-  optional: "evictor" (else no evictor)
      [.allowedLateness(...)]    <-  optional: "lateness" (else zero)
      [.sideOutputLateData(...)] <-  optional: "output tag" (else no side output for late data)
       .reduce/aggregate/fold/apply()      <-  required: "function"
      [.getSideOutput(...)]      <-  optional: "output tag"

Non-Keyed Windows

stream
       .windowAll(...)           <-  required: "assigner"
      [.trigger(...)]            <-  optional: "trigger" (else default trigger)
      [.evictor(...)]            <-  optional: "evictor" (else no evictor)
      [.allowedLateness(...)]    <-  optional: "lateness" (else zero)
      [.sideOutputLateData(...)] <-  optional: "output tag" (else no side output for late data)
       .reduce/aggregate/fold/apply()      <-  required: "function"
      [.getSideOutput(...)]      <-  optional: "output tag"

在上面,方括号([…])中的命令是可选的。 这表明Flink允许您以多种不同方式自定义窗口逻辑,从而使其最适合您的需求。

名词解释:

keyBy:按照一个Key进行分组
window:将数据流中的元素分配到相应的窗口中
windowAll:不分组,将数据流中的所有元素分配到相应的窗口中
trigger:指定触发器Trigger(可选)
evictor:指定清除器Evictor(可选)
allowedLateness:将窗口关闭时间再延迟一段时间
sideOutputLateData:所有过期延迟数据,指定窗口已经彻底关闭了,就会把数据放到侧输出流
.reduce/aggregate/fold/apply(): 窗口处理函数Window Function

二、分类

flink为我们提供了 Window Assigner(窗口分配器)

窗口分配器定义了如何将元素分配给窗口。这是通过在window(…)(对于键控流)或windowAll()(对于非键控流)调用中指定您选择的WindowAssigner来完成的。

按照窗口的Assigner来分,窗口可以分为
Tumbling window,
sliding window,
Session Window,
global window,
custom window,
count window

窗口可以是时间驱动的(Time Window,例如:每30秒钟),也可以是数据驱动的(Count Window,例如:每一百个元素)。

一种经典的窗口分类可以分成:
翻滚窗口(Tumbling Window,无重叠)
滚动窗口(Sliding Window,有重叠),
和会话窗口(Session Window,活动间隙)。

1、时间驱动窗口
在这里插入图片描述
2、数据驱动窗口
在这里插入图片描述
3、会话驱动窗口
在这里插入图片描述

三、实现

我们看一下官方的实现

1、Tumbling windows

DataStream<T> input = ...;

// tumbling event-time windows
input
    .keyBy(<key selector>)
    .window(TumblingEventTimeWindows.of(Time.seconds(5)))
    .<windowed transformation>(<window function>);

// tumbling processing-time windows
input
    .keyBy(<key selector>)
    .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
    .<windowed transformation>(<window function>);

// daily tumbling event-time windows offset by -8 hours.
input
    .keyBy(<key selector>)
    .window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(-8)))
    .<windowed transformation>(<window function>);

2、Sliding windows

DataStream<T> input = ...;

// sliding event-time windows
input
    .keyBy(<key selector>)
    .window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
    .<windowed transformation>(<window function>);

// sliding processing-time windows
input
    .keyBy(<key selector>)
    .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
    .<windowed transformation>(<window function>);

// sliding processing-time windows offset by -8 hours
input
    .keyBy(<key selector>)
    .window(SlidingProcessingTimeWindows.of(Time.hours(12), Time.hours(1), Time.hours(-8)))
    .<windowed transformation>(<window function>);

3、Session windows

DataStream<T> input = ...;

// event-time session windows with static gap
input
    .keyBy(<key selector>)
    .window(EventTimeSessionWindows.withGap(Time.minutes(10)))
    .<windowed transformation>(<window function>);
    
// event-time session windows with dynamic gap
input
    .keyBy(<key selector>)
    .window(EventTimeSessionWindows.withDynamicGap((element) -> {
        // determine and return session gap
    }))
    .<windowed transformation>(<window function>);

// processing-time session windows with static gap
input
    .keyBy(<key selector>)
    .window(ProcessingTimeSessionWindows.withGap(Time.minutes(10)))
    .<windowed transformation>(<window function>);
    
// processing-time session windows with dynamic gap
input
    .keyBy(<key selector>)
    .window(ProcessingTimeSessionWindows.withDynamicGap((element) -> {
        // determine and return session gap
    }))
    .<windowed transformation>(<window function>);

4、Global Windows

DataStream<T> input = ...;

input
    .keyBy(<key selector>)
    .window(GlobalWindows.create())
    .<windowed transformation>(<window function>);

相关唇口方法中可以使用Time.milliseconds(x)Time.seconds(x)Time.minutes(x) 等之一来指定时间间隔。

窗口分配器还采用可选的offset参数,该参数可用于更改窗口的对齐方式。 例如,在没有偏移的情况下,每小时滚动窗口与标注时间对齐,即您将获得诸如1:00:00.000-1:59:59.9992:00:00.000-2:59:59.999之类的窗口。 如果要更改,可以提供一个偏移量。 例如,使用15分钟的偏移量,您将获得1:15:00.000-2:14:59.9992:15:00.000-3:14:59.999等。

偏移量的重要用例是将窗口调整为时区 除了UTC-0。 例如,在中国,您将必须指定**Time.hours(-8)**的偏移量。

注意:窗口左闭右开

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值