Flink分区和窗口操作

发布于:2024-07-05 ⋅ 阅读:(12) ⋅ 点赞:(0)

分区(Partitioning)与分组(Grouping):

分区:

  • 将数据流划分为多个子流,每个子流由一个或多个子任务处理。
  • 通过 keyBy 操作实现,根据键对数据进行分区。
  • 数据具体去往哪个分区,是通过指定的 key 值先进行一次 hash 再进行一次MurmurHash,通过上述计算得到的值再与并行度进行相应的计算得到。
  • 分区的目的是实现数据并行处理,提高处理性能和吞吐量。

分组:

  • 根据特定键将数据进行逻辑上的划分,以便对相同键的数据进行聚合操作。
  • 结合窗口操作(如 timeWindow)使用,在分区后的数据流中对相同键的数据进行聚合计算。
  • 在聚合操作中,将相同键的事件聚合在一起进行处理。

示例:

DataStream<MyEvent> groupedStream = stream
	// keyBy 分区操作
    .keyBy(event -> event.getKey())
    // 分组操作
    .timeWindow(Time.minutes(5))
    .sum("value");

数据如果具有相同的 key 将一定去往同一个分组和分区,但是同一分区中的数据不一定属于同一组。

分区中的按键分区(Keyed)和非按键分区(Non-Keyed)

  • 按键分区窗口(Keyed Windows)
    • 经过按键分区keyBy操作后,数据流会按照key被分为多条逻辑流(logical streams),这就是KeyedStream。
    • 基于KeyedStream进行窗口操作时,窗口计算会在多个并行子任务上同时执行。相同key的数据会被发送到同一个并行子任务。
  • 非按键分区(Non-Keyed Windows)
    • 如果没有进行keyBy,那么原始的DataStream就不会分成多条逻辑流。窗口逻辑只能在一个任务(task)上执行,并行度为1。
    • 非按键分区的窗口操作,手动调大窗口算子的并行度也是无效的。
# Keyd windows
stream.keyBy().window()
# Non-Keyd windows
stream.windowAll()

窗口的分类

按照截取数据的方式(驱动类型)分类:

  • 时间窗口(Time Window): 时间点来截取数据。
  • 计数窗口(Count Window): 元素的个数来截取数据。

按照窗口分配数据的规则分类:

  • 滚动窗口(Tumbling Window)
    • 窗口之间不重叠,也不会有间隔。
    • 每个数据都会被分配到唯一的窗口中。
    • 可以用时间或者数量定义窗口的大小。
  • 滑动窗口(Sliding Window)
    • 类似滑动窗户,窗口大小固定,窗口之间可以重叠。
    • 参数有窗口的大小和滑动的步长。
    • 数据可以同时被分配到多个窗口中,适合结果更新非常快的场景。
    • 可以用时间或者数量定义窗口的大小。
  • 会话窗口(Session Window)
    • 通过会话来对数据进行分组,只能基于时间----会话的超时时间。
    • 会话的长度不固定,分区之间窗口没有关联,会话窗口之间一定是不会重叠的,并且可能会留有GapSize.
    • 适用保持会话的场景。
  • 以及全局窗口(Global Window)
    • 没有结束的窗口,包含所有的key,默认不会触发计算。
    • 预留用来自定义窗口函数。

窗口计算的4个重要的组成部分:

  1. assigner(分配器):如何将元素分配给窗口。
  2. function(计算函数):为窗口定义的计算。其实是一个计算函数,完成窗口内容的计算。
  3. triger(触发器):在什么条件下触发窗口的计算。
  4. evictor(退出器):定义从窗口中移除数据。

窗口的其他特性:

  • 窗口的区间是左闭右开,窗口的最大时间戳 = end - 1ms。
  • 当属于某个窗口的第一个元素到达,Flink 就会创建一个窗口。
  • 时间进展 >= 窗口最大时间戳 + 窗口允许延迟时间。这样的窗口就能销毁掉。

网站公告

今日签到

点亮在社区的每一天
去签到