CodeWalk

Flink Watermark机制

作者:我还是少年 · 2026-05-30 12:55

请解释Flink中Watermark(水位线)的概念、作用以及如何处理乱序事件。

回答

我还是少年

Watermark定义: 一种时间进度指标,表示系统认为在该时间戳之前的所有事件已经到达(或应该不再期望更晚的事件)。

为什么要Watermark:

  • 数据到达存在乱序(Out-of-Order)延迟(Late)
  • 需要确定何时触发窗口计算——不能永远等待所有数据
  • Watermark是**权衡完整性(Completeness)和延迟(Latency)**的机制

Watermark工作原理:

时间轴:  1    2    3    4    5    6    7    8    9   10
事件:    [A]  [B]  [C]  [D]       [E]  [F]  [G]       [H]
Watermark:      3         5             8              10
(Watermark=3时,所有≤3的事件都已到达)

Watermark生成方式:

1. 周期性Watermark(Periodic):

// 每100ms生成一次Watermark
env.getConfig().setAutoWatermarkInterval(100);

// 允许最大乱序时间为5秒
watermarkStrategy = WatermarkStrategy
  .<Event>forBoundedOutOfOrderness(Duration.ofSeconds(5))
  .withTimestampAssigner((event, timestamp) -> event.timestamp);

2. 断点式Watermark(Punctuated):

  • 当遇到特定标记事件时生成,适合有明确结束信号的场景

窗口触发时机:

  • 当Watermark ≥ 窗口结束时间 时触发窗口计算
  • 如:[10:00:00, 10:00:10)的窗口,在水位线≥10:00:10时触发

处理延迟数据:

  1. Allowed Lateness: 设置允许延迟时间,延迟数据仍然更新窗口(但需要再次触发)
  2. Side Output: 无法处理的超迟数据输出到侧输出流(Side Output)
  3. 丢弃(默认): 舍弃超时的数据
window(TumblingEventTimeWindows.of(Time.seconds(10)))
  .allowedLateness(Time.seconds(5))
  .sideOutputLateData(lateOutputTag)