Flink窗口

本文详细介绍了Flink中的窗口机制,包括时间窗口和计数窗口,以及它们的驱动类型和数据分配规则。重点讲述了滚动窗口、滑动窗口、会话窗口和全局窗口的概念和应用场景。此外,还讨论了窗口的触发器、移除器、允许延迟以及侧输出流,深入理解Flink如何处理实时流数据的实时计算和数据处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 窗口
    在上一章中已经了解了 Flink 中事件时间和水位线的概念,那它们有什么具体应用呢?当然是做基于时间的处理计算了。其中最常见的场景,就是窗口聚合计算。 之前我们已经了解了 Flink 中基本的聚合操作。在流处理中往往面对的是连续不断、无休无止的无界流,不可能等到所有所有数据都到齐了才开始处理。所以聚合计算其实 只能针对当前已有的数据——之后再有数据到来,就需要继续累加、再次输出结果。这样似乎 很“实时”,但现实中大量数据一般会同时到来,需要并行处理,这样频繁地更新结果就会给 系统带来很大负担了。 更加高效的做法是,把无界流进行切分,每一段数据分别进行聚合,结果只输出一次。这 就相当于将无界流的聚合转化为了有界数据集的聚合,这就是所谓的“窗口”(Window )聚合 操作。窗口聚合其实是对实时性和处理效率的一个权衡。在实际应用中,我们往往更关心一段 时间内数据的统计结果,比如在过去的一 分钟内有多少用户点击了网页。在这种情况下,我们 就可以定义一个窗口,收集最近一分钟内的所有用户点击数据,然后进行聚合统计,最终输出 一个结果就可以了。 在 Flink 中,提供了非常丰富的窗口操作,下面我们就来详细介绍。

     
  •  窗口的概念
    Flink 是一种流式计算引擎,主要是来处理无界数据流。想 要更加方便高效地处理无界流,一种方式就是将无限数据切割成有限的“数据块进行处理,这 就是所谓的“窗口Window)。 在 Flink 中, 窗口就是用来处理无界流的核心。我们很容易把窗口想象成一个固定位置的 “框,数据源源不断地流过来,到某个时间点窗口该关闭了,就停止收集数据、触发计算并输 出结果。例如,我们定义一个时间窗口,每 10 秒统计一次数据,那么就相当于把窗口放在那 里,从 0 秒开始收集数据;到 10 秒时,处理当前窗口内所有数据,输出一个结果,然后清空 窗口继续收集数据;到 20 秒时,再对窗口内所有数据进行计算处理,输出结果;依次类推, 如图所示。

    这里注意为了明确数据划分到哪一个窗口,用数学符号表示就是一个左闭右开的区间,例如 0~10 秒的窗口可以表示为[0, 10),这里单 位为秒。对于处理时间下的窗口而言,这样理解似乎没什么问题。因为窗口的关闭是基于系统时间的,当前窗口关闭就只能去下一个窗口正如上图中,0~10 秒的窗口关闭后,可能还有时间戳为 9 的数据会来,它就只能进入 10~20 秒的窗口了。这样会造成窗口处理结果的不准确。所以我们需要设置一个延迟时间来等所有数据到齐。比如上面的例子中,我们可以设置延迟时间为 2 秒,这样 0~10 秒的窗口会在时间戳为 12 的数据到来之后,才真正关闭计算输出结果,这 样就可以正常包含迟到的 9 秒数据了如图所示。

    但是这样一来, 0~10 秒的窗口不光包含了迟到的 9 秒数据,连 11 秒和 12 秒的数据也包
    含进去了。我们为了正确处理迟到数据,结果把早到的数据划分到了错误的窗口——最终结果
    都是错误的。 所以相比之下,我们应该把窗口理解成一个“桶” 。在 Flink 中,窗口可以把流切割成有限大小的多个“存储桶”(bucket) ;每个数据都会分发到对应的桶中,当到达窗口结束时间时,就对每个桶中收集的数据进行计算处理如图所示。

    我们可以梳理一下事件时间语义下,之前例子中窗口的处理过程:
    1 )第一个数据时间戳为 2 ,判断之后创建第一个窗口 [0, 10 ),并将 2 秒数据保存进去;
    (2)后续数据依次到来,时间戳均在 [0, 10 )范围内,所以全部保存进第一个窗口;
    (3) 11 秒数据到来,判断它不属于 [0, 10 )窗口,所以创建第二个窗口 [10, 20 ),并将 11
    秒的数据保存进去。由于水位线设置延迟时间为 2 秒,所以现在的时钟是 9 秒,第一个窗口也
    没有到关闭时间;
    (4)之后又有 9 秒数据到来,同样进入 [0, 10 )窗口中;
    (5) 12 秒数据到来,判断属于 [10, 20 )窗口,保存进去。这时产生的水位线推进到了 10
    秒,所以 [0, 10 )窗口应该关闭了。第一个窗口收集到了所有的 7 个数据,进行处理计算后输
    出结果,并将窗口关闭销毁;
    (6)同样的,之后的数据依次进入第二个窗口,遇到 20 秒的数据时会创建第三个窗口 [20,30)并将数据保存进去;遇到 22 秒数据时,水位线达到了 20 秒,第二个窗口触发计算,输出结果并关闭。
    这里需要注意的是, Flink 中窗口并不是静态准备好的,而是动态创建——当有落在这个
    窗口区间范围的数据达到时,才创建对应的窗口。另外,这里我们认为到达窗口结束时间时,
    窗口就触发计算并关闭,事实上“触发计算”和“窗口关闭”两个行为也可以分开,这部分内
    容我们会在后面详述。

     
  • 窗口的分类
    Flink 中,窗口的应用非常灵活,我们可以使用各种不同类型的窗口来实现需求。接下来我们就从不同的角度,对Flink中内置的窗口做一个分类说明。
  • 按照驱动类型分类:
    窗口本身是截取有界数据的一种方式。换句话说,就是以什么方式来开始和结束数据的截取,我们把它叫作窗口的“驱动类 型”。 我们最容易想到的就是按照时间段去截取数据,这种窗口就叫作“时间窗口”(Time Window)。之前所举的例子也都是时间窗口。除了由时间驱动之外, 窗口其实也可以由数据驱动,也就是说按照固定的数量,来截取一段数据集,这种窗口叫作“计数窗口”(Count Window),如图所示。

    1)时间窗口(Time Window):
         时间窗口以时间点来定义窗口的开始时间 和结束时间,截取出的就是某一时间段的数。到结束时间时, 窗口不再收集数据, 触发计算输出结果, 并将窗口关闭销毁。
         用结束时间减去开始时间,得到这段时间的长度, 就是窗口的大小(window size)。这里的时间可以是不同的语义,既可以是处理时间窗口也可以是事件时间窗口。
         Flink
     中有一个专门的类来表示时间窗口, 称就叫作 TimeWindow。这个类只有两个私 有属性:start end ,表示窗口的开始和结束的时间戳,单位为毫秒。另外,TimeWindow 还提供了一个 maxTimestamp()
    方法,用来获取窗口中能够包含数据的最大时间戳
    2)计数窗口(Count Window):
         计数窗口基于元素的个数来截取数据,到达固定的个数时就触发计算并关闭窗口。每个窗口截取数据的个数,就是窗口的大小。
         计数窗口相比时间窗口就更加简单,只需指定窗口大小,就可以把数据分配到对应的窗口中了。在 Flink
    内部也并没有对应的类来表示计数窗口,底层是通过“全局窗口”(Global Window)来实现的。

  • 按照窗口分配数据的规则分类: 
    时间窗口和计数窗口,只是对窗口的一个大致划分;在具体应用时,还需要定义更加精细
    的规则,来控制数据应该划分到哪个窗口中去。不同的分配方式,就可以有不同的功能。
    根据分配数据的规则,窗口的具体实现可以分为 4 类:滚动窗口( Tumbling Window )、 <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值