CodeWalk

Flink Watermark与Allowed Lateness

作者:编译有声 · 2026-05-30 12:55

Flink中的Watermark和Allowed Lateness分别解决了什么问题?请说明Watermark的生成机制(Periodic/Punctuated)、传播原理以及如何影响窗口触发时机。Allowed Lateness如何与Watermark配合保证迟到数据仍能被处理?

回答

编译有声

1. Watermark概念

Watermark是Flink中表示事件时间进度的机制:

// Watermark = 观察到的时间戳 - 允许的最大乱序时间
// 例如:max_ts=10:00, max_out_of_order=5min
// Watermark = 09:55
// 含义:所有 <= 09:55 的数据都已经到达

2. Watermark生成

周期性(Periodic)

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

// 自定义生成器
AssignerWithPeriodicWatermarks<String> allocator = 
  new BoundedOutOfOrdernessTimestampExtractor
    <String>(Time.seconds(10)) {
    @Override
    public long extractTimestamp(String element) {...}
};

间断性(Punctuated)

// 每来一条特殊标记的数据生成Watermark
// 适用于数据本身带有Watermark信息的场景

3. 窗口触发条件

窗口 [10:00, 10:05) 触发条件:
1. Watermark >= 10:05(窗口结束时间)
2. 并且该窗口内至少有一条数据

4. Allowed Lateness

// 允许迟到5分钟
WindowedStream<...> windowed = stream
  .keyBy(...)
  .window(TumblingEventTimeWindows.of(Time.minutes(10)))
  .allowedLateness(Time.minutes(5))
  .sideOutputLateData(lateOutputTag);

工作原理

Watermark=10:05时,窗口[10:00,10:05)触发
但状态保留5分钟
在10:10之前到达的迟到数据(时间戳在[10:00,10:05))
  仍可进入该窗口
  触发窗口的update回调

5. 完整流程

数据时间戳 | Watermark | 状态
10:03      | 09:53     | 缓冲
10:06      | 09:56     | 缓冲
10:08      | 09:58     | Watermark推进
10:15      | 10:05     | 窗口[10:00,10:05)触发!输出结果
           |           | 窗口状态保留5分钟
10:03(迟到)| 10:06     | 迟到数据,但还在lateness范围内
           |           | 触发窗口更新,再次输出
10:12      | 10:07     | 迟到超过5分钟→Side Output

6. 最佳实践

// Kappa架构中设置合理的Watermark延迟
// 实时场景:5-10秒
// 准实时场景:1-5分钟
// 批流一体场景:可接受小时级延迟

// 监控迟到数据比例
DataStream<...> lateStream = result.getSideOutput(lateTag);
lateStream.addSink(new LateDataLogger());