订阅更新

Flink 窗口怎么选?滚动、滑动、会话有什么区别?

面试问 028 约 3 分钟读完 3 次阅读

本文目录
  1. 面试怎么回答
  2. 第一步:滚动窗口适合固定周期统计
  3. 第二步:滑动窗口适合持续观察最近一段时间
  4. 第三步:会话窗口适合没有固定边界的行为过程
  5. 第四步:选完窗口类型,还要回答四个问题
  6. 一个典型场景

面试怎么回答

滚动窗口固定且不重叠,适合按分钟、小时做周期统计;滑动窗口由大小和步长决定,会重叠,适合持续观察最近一段时间,但要关注一条数据进入多个窗口带来的状态和计算成本;会话窗口按不活跃间隔动态切分,适合用户访问这类没有固定边界的过程。实际选择时,我还会明确 Event Time、Watermark、分组 Key、迟到数据和聚合方式,而不是只比较三个定义。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

很多人会回答:

“滚动窗口不重叠,滑动窗口会重叠,会话窗口按用户活跃间隔切分。”

定义没错,但还不够。

面试官真正想听的是:

你能不能从业务问题、输出频率、时间语义和状态成本出发,选出合适的窗口。


第一步:滚动窗口适合固定周期统计

滚动窗口有固定大小,相邻窗口之间不重叠,一条数据只属于一个窗口。

例如每 5 分钟统计一次订单量:

[10:00, 10:05)
[10:05, 10:10)
[10:10, 10:15)

它适合固定报表、定时告警、每小时或每天汇总等场景。

优点是语义清晰、状态和计算成本相对可控;缺点是窗口边界很明显,无法直接回答“任意时刻最近 30 分钟”的问题。


第二步:滑动窗口适合持续观察最近一段时间

滑动窗口由两个参数决定:窗口大小和滑动步长。

例如“每 1 分钟计算最近 10 分钟的请求量”:

窗口大小:10 分钟
滑动步长:1 分钟

窗口之间会重叠,同一条数据可能进入多个窗口。

它适合实时趋势、滚动指标和连续告警,但代价也更高。窗口大小是 24 小时、步长是 1 分钟时,一条数据理论上可能参与约 1440 个窗口的计算。

所以滑动窗口不能只看业务效果,还要评估:

  • 窗口大小与步长的比例
  • 状态量和输出频率
  • 是否使用增量聚合,而不是把所有明细都攒到窗口结束
  • 业务是否真的需要这么高的刷新频率

第三步:会话窗口适合没有固定边界的行为过程

会话窗口没有固定长度,而是根据“不活跃间隔”判断会话是否结束。

例如设置 30 分钟 Session Gap:同一用户持续产生行为时,会话不断延长;超过 30 分钟没有新事件,当前会话才关闭。

它适合用户访问、设备连接、游戏对局等自然会话场景。

但它也更依赖数据质量和时间语义。迟到事件可能让两个原本分开的会话重新合并,状态管理和结果更新会更复杂。

Flink 三类窗口时间线


第四步:选完窗口类型,还要回答四个问题

窗口类型只是第一层,生产设计里还要继续确认:

1. 用 Event Time 还是 Processing Time?

如果统计要反映事件真实发生时间,通常优先考虑 Event Time,并设计 Watermark 和迟到数据策略;如果只关心系统当前处理速度,Processing Time 更简单,但结果会受延迟和重启影响。

2. 按什么 Key 分组?

窗口通常应该在 keyBy 后执行,让不同 Key 并行计算。直接使用 windowAll 会把数据汇总到单个并行实例,容易形成性能瓶颈。

3. 什么时候触发、迟到多久还能更新?

要明确 Trigger、Allowed Lateness 和 Side Output,否则迟到数据到底丢弃、补算还是更新旧结果,口径会不一致。

4. 窗口里保存明细还是增量结果?

能用 ReduceFunction 或 AggregateFunction 增量聚合,就尽量不要等窗口结束后再一次性遍历全部明细。


一个典型场景

比如业务要“每分钟展示最近 24 小时 UV”,直接设计 24 小时大小、1 分钟步长的滑动窗口。

需求看起来合理,但窗口重叠比例非常高。如果每条事件被重复分配到大量窗口,并在窗口里保存完整明细,状态、Checkpoint 和输出压力都会快速上升。

这时不能只说“把并行度调大”。应该重新评估一分钟刷新是否必要,并结合增量聚合、分层预聚合或更适合的去重状态方案降低重复计算。

窗口不是时间参数配置题,而是业务实时性、结果准确性和资源成本的取舍题。


刷题进度保存在当前浏览器