专栏首页SmartSiFlink 窗口之Window机制

Flink 窗口之Window机制

数据分析场景见证了批处理到流处理的演变过程。尽管批处理可以作为流处理的一种特殊情况来处理,但分析永无止境的流数据通常需要转变一种思维方式,并使用它自己的专门术语,例如,窗口、At-Least-Once 或者 Exactly-Once 处理语义。

对于刚刚接触流处理的人来说,这种思维方式的转变以及新的专业术语可能会让他们感到非常困惑。但是,Apache Flink 作为一个为生产环境而生的流处理器,具有易于使用并且表达能力很强的 API 来定义高级流分析程序。 Flink 的 API 在数据流上有非常灵活的窗口定义,使其能在其他开源流处理器中脱颖而出。

在这篇文章中,我们主要讨论用于流处理的窗口的概念,介绍 Flink 的内置窗口,并说明其对自定义窗口语义的支持。

1. 什么是窗口?它们有什么用?

我们拿交通传感器的例子来说明,传感器每15秒统计通过某个位置的车辆数量。结果流看起来像如下所示:

如果现在我们想知道有多少辆车经过这个位置,我们只需简单的将每15秒统计的数量相加即可。但是,传感器流的本质是连续产生数据。像这样的流永远都不会结束,更不可能计算出可以返回的最终和。换一种思路,我们可以滚动计算总和,即为每个输入事件返回一个更新的总和记录。这就会产生新的部分和流:

但是,部分求和流可能不是我们想要的,因为它会不断更新计数,更重要的是,某些信息(例如随时间变化)会丢失。因此,我们需要想改一下我们的问题:每分钟通过该位置的汽车数量。这要求我们将流的元素分组为有限的集合,每个集合对应于60秒。此操作称为滚动窗口操作。

滚动窗口将流离散化为不重叠的窗口。对于某些应用程序,重要的是窗口不可分离,因为应用程序可能需要平滑的聚合。例如,我们可以每30秒计算最后一分钟通过的汽车数量。这种窗口称为滑动窗口。

如上所述,在数据流上定义窗口是非并行操作。这是因为流的每个元素必须由同一窗口算子处理,决定每个元素应归属到哪个窗口中。一个完整流上的 Windows 在 Flink 中称为 AllWindows。对于许多应用程序,数据流可以拆分为多个逻辑流,每个逻辑流都可以应用窗口算子。例如,考虑统计来自多个交通传感器(而不是像前面的示例中的一个传感器)的车辆,其中每个传感器都会监控一个不同的位置。通过按传感器ID对流进行分组,我们可以并行计算每个位置的窗口流量统计。在 Flink 中,我们将这种分区的窗口简称为 Windows,因为它们是分布式流的常见情况。下图显示了在 (sensorId, count) 流上的滚动窗口。

一般来说,窗口在无界流上定义了一组有限的元素。该集合可以基于时间(如我们之前的示例中所示),元素个数,元素个数和时间的组合或一些自定义逻辑将元素分配给窗口。Flink 的 DataStream API 为最常见的窗口操作提供了简洁的算子,并提供了一种通用的窗口机制,该机制允许用户自定义窗口逻辑。在下面的内容中,我们将介绍 Flink 的 Time Windows 和 Count Windows,然后再详细讨论其窗口机制。

2. Time Windows

顾名思义,Time Windows(时间窗口)按时间对流元素进行分组。例如,窗口大小为一分钟的滚动窗口将收集一分钟内的元素,并在一分钟后将函数应用于窗口中的所有元素。在 Apache Flink 中定义滚动和滑动时间窗口非常简单:

// Stream of (sensorId, carCnt)
DataStream<Tuple2<String, Long>> vehicleCnt ...

// 滚动窗口
DataStream<Tuple2<String, Long>> tumblingCnt = vehicleCnt
        // 根据sensorId分组
        .keyBy(0)
        // 窗口大小为1分钟的滚动窗口
        .timeWindow(Time.minutes(1))
        // 求和
        .sum(1);

// 滑动窗口
DataStream<Tuple2<String, Long>> slidingCnt = vehicleCnt
        // 根据sensorId分组
        .keyBy(0)
        // 窗口大小为1分钟、滑动步长为30秒的滑动窗口
        .timeWindow(Time.minutes(1), Time.seconds(30))
        // 求和
        .sum(1);

我们还没有讨论过 ‘收集一分钟内的元素’ 的确切含义,也可以归结为’流处理器如何解释时间?’这一问题。

Apache Flink 具有三种不同的时间概念,即处理时间,事件时间和摄取时间。具体的可以参阅Flink 事件时间与处理时间

3. Count Windows

除了 Time Windows 外,Apache Flink 还具有 Count Windows(计数窗口)。一个大小为100的滚动计数窗口,将会在一个窗口中收集100个元素,并在添加第100个元素时触发窗口计算。

在 Flink 的 DataStream API 中,滚动和滑动计数窗口如下定义:

// Stream of (sensorId, carCnt)
DataStream<Tuple2<String, Long>> vehicleCnt ...

// 滚动窗口
DataStream<Tuple2<String, Long>> tumblingCnt = vehicleCnt
        // 根据sensorId分组
        .keyBy(0)
        // 100个元素大小的滚动计数窗口
        .countWindow(100)
        // 求和
        .sum(1);

// 滑动窗口
DataStream<Tuple2<String, Long>> slidingCnt = vehicleCnt
        // 根据sensorId分组
        .keyBy(0)
        // 100个元素大小、步长为10个元素的滑动计数窗口
        .countWindow(100, 10)
        // 求和
        .sum(1);

4. 剖析Flink的窗口机制

Flink 的内置 Time Windows 和 Count Windows 覆盖了各种常见的窗口用例。但是,有些应用程序还是需要实现自定义窗口逻辑,而 Flink 的内置窗口无法解决这些逻辑。为了同时也支持定制的窗口语义的应用程序,DataStream API 公开了窗口机制内部的接口。这些接口可以非常精细地控制窗口的创建和触发。

下图描述了 Flink 的窗口机制,并介绍了其中涉及的组件。

到达窗口算子的元素将传递给 WindowAssigner。 WindowAssigner 将元素分配给一个或多个窗口,也可能会创建新的窗口。窗口本身只是一系列元素的标识符,并且可以提供一些可选的元信息,例如,在使用 TimeWindow 时的开始和结束时间。请注意,可以将元素添加到多个窗口中,这也意味着可以同时存在多个窗口。

每个窗口都有一个 Trigger,决定了何时触发计算或清除该窗口。当先前注册的计时器到点时,对于分配到窗口中的每个元素都会调用 Trigger。对于每个事件,Trigger 都可以决定触发,清除(清除窗口并丢弃其内容),或者触发并清除窗口。仅触发的 Trigger 会计算窗口并保持其原样,即所有元素都保留在窗口中,并在下次触发时再次计算(不删除元素)。一个窗口可以被触发多次计算,并且一直存在直到清除为止。请注意,在清除窗口之前,窗口会一值消耗内存。

触发 Trigger 时,可以将窗口元素列表提供给可选的 Evictor。Evictor 遍历列表,可以决定从列表的开头删除一些元素,即删除一些首先进入窗口的元素。其它元素则提供给窗口计算函数。如果没有定义 Evictor,则 Trigger 直接将所有窗口元素交给窗口计算函数。

窗口计算函数接收一个窗口的元素(可能先由 Evictor 进行过滤),并为该窗口计算一个或多个结果元素。DataStream API 可以接受不同类型的计算函数,包括预定义的聚合函数,例如,sum(),min(),max() 以及 ReduceFunction,FoldFunction 或 WindowFunction。WindowFunction 是最通用的窗口计算函数,接收窗口对象(即窗口的元数据),窗口元素列表以及窗口键(如果是 Keyed Window)作为参数。

这些是构成 Flink 的窗口机制的组件。

5. 结论

对于现代流处理器来说,在连续数据流上支持各种类型的窗口是必不可少的。Apache Flink 是一种流处理器,具有非常强大的功能,其中就包括一种非常灵活的机制来构建和计算连续数据流上的窗口。Flink 为常见用例提供了内置的窗口算子,以及允许用户自定义窗口逻辑。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 《从0到1学习Flink》—— 介绍Flink中的Stream Windows

    目前有许多数据分析的场景从批处理到流处理的演变, 虽然可以将批处理作为流处理的特殊情况来处理,但是分析无穷集的流数据通常需要思维方式的转变并且具有其自己的术语(...

    zhisheng
  • Flink学习笔记

    流式计算是大数据计算的痛点,第1代实时计算引擎Storm对Exactly Once 语义和窗口支持较弱,使用的场景有限且无法支持高吞吐计算;Spark Stre...

    数据社
  • Flink 彻底理解 window(窗口)

    Window 是处理无限流的核心。Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层的引擎是一个流式引擎,在上面实现了流处...

    kk大数据
  • [白话解析] Flink的Watermark机制

    对于Flink来说,Watermark是个很难绕过去的概念。本文将从整体的思路上来说,运用感性直觉的思考来帮大家梳理Watermark概念。

    罗西的思考
  • 【Flink】Flink中的窗口函数、时间语义及watermark

    Flink 流应用程序处理的是以数据对象表示的事件流。所以在 Flink 内部,我们需要能够处理这些对象。它们需要被序列化和反序列化,以便通过网络传送它们;或者...

    魏晓蕾
  • Flink实战(七) - Time & Windows编程

    掌握Flink中三种常用的Time处理方式,掌握Flink中滚动窗口以及滑动窗口的使用,了解Flink中的watermark。

    JavaEdge
  • Flink最难知识点再解析 | 时间/窗口/水印/迟到数据处理

    时间、窗口、水印、迟到数据这四个知识点几乎是Flink这个框架最难点。我之前发了很多文章来解释。很多同学仍然理解不了。

    王知无-import_bigdata
  • 大数据Flink面试考题___Flink高频考点,万字超全整理(建议收藏)

    1.下面哪个不是 Dataset的转换算子() A. readTextFile B reduce distinct D rebalance

    ChinaManor
  • Flink Windows窗口简介和使用

    很多人不知道什么是Window?有哪些用途? 下面我们结合一个现实的例子来说明。

    木野归郎
  • 零基础学Flink:Window & Watermark

    在上一篇文章中,我们学习了flink的时间。 本文我们来一起研究下 window 和 watermark 。

    麒思妙想
  • Apache-Flink深度解析-TableAPI

    SQL和Table API是Apache Flink中的同一层次的API抽象,如下图所示:

    王知无-import_bigdata
  • 五万字 | Flink知识体系保姆级总结

    一、Flink简介 二、Flink 部署及启动 三、Flink 运行架构 四、Flink 算子大全 五、流处理中的 Time 与 Window 六、Flink ...

    五分钟学大数据
  • Flink 中极其重要的 Time 与 Window 详细解析(深度好文,建议收藏)

    流式:就是数据源源不断的流进来,也就是数据没有边界,但是我们计算的时候必须在一个有边界的范围内进行,所以这里面就有一个问题,边界怎么确定?无非就两种方式,根据时...

    五分钟学大数据
  • Flink滑动窗口原理与细粒度滑动窗口的性能问题

    Flink的窗口机制是其底层核心之一,也是高效流处理的关键。Flink窗口分配的基类是WindowAssigner抽象类,下面的类图示出了Flink能够提供的所...

    王知无-import_bigdata
  • 【Flink】Flink流应用开发

    (1)Flink简介 Flink是一个低延迟、高吞吐、统一的大数据分布式实时计算引擎,使用官网的一句话来介绍Flink就是“Stateful Computat...

    魏晓蕾
  • 彻底搞清Flink中的Window(Flink版本1.8)

    在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处理,例如:在过...

    create17
  • Flink 中极其重要的 Time 与 Window 详细解析(深度好文,建议收藏)

    流式:就是数据源源不断的流进来,也就是数据没有边界,但是我们计算的时候必须在一个有边界的范围内进行,所以这里面就有一个问题,边界怎么确定? 无非就两种方式,根据...

    五分钟学大数据
  • Apache-Flink深度解析-TableAPI

    在《SQL概览》中我们概要的向大家介绍了什么是好SQL,SQL和Table API是Apache Flink中的同一层次的API抽象,如下图所示

    王知无-import_bigdata
  • Apache Flink窗口的几种实现的类别

    “ 无界数据于有界数据是一个比较于模糊的概念,无界与有界之间是可以进行转换的。无界数据流在进行某些计算的时候例如每分钟、每小时、每天等操作时都可以看做是有界数据...

    CainGao

扫码关注云+社区

领取腾讯云代金券