Flink Watermark与Allowed Lateness
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());