马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
水印(Watermark):用于事件时间处理,标记数据流的进度,办理乱序和耽误标题,触发窗口计算
一、Flink 水印的作用
- 处理乱序事件
水印(Watermark)是 Flink 用于处理事件时间(Event Time)乱序数据的核心机制。水印表示“在该时间戳之前的数据已全部到达”,允许体系在不确定数据顺序的情况下推进计算进度。
- 触发窗口计算
当水印时间超过窗口的结束时间时,触发窗口计算并关闭窗口,确保窗口内的数据完备性。
- 容忍数据耽误
通过设置允许耽误时间(如 BoundedOutOfOrderness),水印可等候肯定范围内的迟到数据,避免因短暂乱序导致数据丢失。
二、水印判断数据迟到的逻辑
水印通过以下机制判断迟到数据:
- 基准界说
- 水印时间T表示事件时间≤T的数据应已到达体系。
- 任何事件时间≤T但晚于水印到达的数据视为迟到。
- 窗口触发与迟到处理
- 窗口触发条件:水印时间 ≥ 窗口结束时间。
- 窗口关闭后,事件时间属于该窗口的数据将被丢弃或通过侧输出(Side Output)处理。
- 允许耽误(Allowed Lateness):窗口可额外等候一段时间(如3秒),耽误期内到达的数据仍可被处理。
计谋选择原则:根据数据乱序水平选择固定耽误或单调递增计谋,极端乱序场景需团结侧输出(Side Output)处理异常事件。
高乱序场景优先采取事件时间窗口+水印机制。
三、水印的初次天生原理
1. 初始触发条件
水印的初次天生依赖于第一条到达的事件数据。体系提取其事件时间戳,团结允许耽误时间计算初始水印。
- 公式:初始水印时间 = 第一条数据的事件时间 - 允许耽误时间
- 示例:若第一条数据的事件时间为 10:00,允许耽误为 5分钟,则初始水印为09:55。
2. 动态更新机制
后续水印根据新到达数据的事件时间动态更新,始终以当前最大事件时间为基准。
四、水印的天生计谋
- 固定耽误计谋(BoundedOutOfOrderness)
显式指定允许的最大耽误时间,适用于数据存在可控乱序的场景。
- WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofMinutes(5))
复制代码 该计谋天生的水印时间 = 当前最大事件时间 - 允许耽误时间。
- 单调递增计谋(forMonotonousTimestamps)
假设数据严格有序,允许耽误时间设为 0,水印时间即是当前最大事件时间。适用于数据源自己有序的场景。
- 自界说天生计谋
通过实现 WatermarkGenerator 接口,根据业务逻辑动态调整水印天生规则(如根据事件特性或外部体系状态)。
五、数据乱序时势件时间窗口 vs. 处理时间窗口
对比维度基于事件时间的窗口基于处理时间的窗口时间基准数据自带的事件时间戳体系处理时间(无需水印)水印作用办理乱序标题,动态控制窗口关闭机遇无关联,窗口直接按体系时间分别乱序处理能力通过水印耽误窗口关闭,允许迟到数据进入窗口无法处理乱序,窗口按固定时间触发典型配置需指定 TimestampAssigner 和 WatermarkStrategy仅需界说窗口大小和滑动间隔 核心差别阐明
- 事件时间窗口:依赖水印动态调整窗口关闭时间,水印天生与数据事件时间强相关。例如,若数据时间戳跳跃式增长,水印会快速推进,大概导致中心窗口提前关闭。
- 处理时间窗口:完全基于体系时钟,窗口触发与数据实际到达顺序无关,无法感知事件时间的乱序标题。
六、风险对体系的影响及应对计谋
1. 潜在风险
- 窗口提前关闭:若事件时间突然大幅推进(如从10:00跳跃到12:00),大概导致中心窗口(如10:00-11:00)因水印跨越而提前关闭,后续数据无法进入这些窗口。
- 数据倾斜:时间戳异常事件大概导致水印频仍推进,增加窗口计算频率和资源消耗。
2. 优化配置
- 限制水印推进速度:通过BoundedOutOfOrderness计谋设置最大允许耽误时间,避免因偶发大时间戳事件导致水印异常推进。
示例代码:
- WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofMinutes(5))
复制代码
- 侧输出异常事件:对时间戳显著偏离当前窗口范围的事件,通过侧输出(Side Output)单独处理
示例:
- OutputTag<Event> anomalousTag = new OutputTag<>("anomalous"){};
- stream.process(new ProcessFunction<Event, Event>() {
- @Override
- public void processElement(Event event, Context ctx, Collector<Event> out) {
- if (event.getTimestamp() > ctx.timerService().currentWatermark() + MAX_SKEW) {
- ctx.output(anomalousTag, event);
- } else {
- out.collect(event);
- }
- }
- });
复制代码 七、典型场景示例
假如第一个事件事件是10:00,基于事件时间滚动窗口为5分钟,
那么第一个窗口范围是多少?
假如允许迟到2分钟,第一个水印时间是多少?
触动第一个窗口关闭的水印时间是多少?
那么10:06的事件会被分到第几个窗口呢?
第一个窗口范围
当第一个事件的事件时间为 10:00,基于事件时间的滚动窗口为5分钟时,第一个窗口的范围是 [10:00, 10:05),第二个窗口:[10:05, 10:10),以此类推。
滚动窗口将事件时间分别为固定长度且不重叠的区间,每个窗口的起始时间为事件时间的整数倍12。例如,事件时间 10:00 会被分配到 10:00-10:05 的窗口。
允许迟到2分钟时的第一个水印时间
若允许迟到时间为2分钟,第一个水印时间为 9:58。
水印时间计算公式为:水印时间 = 当前最大事件时间 - 允许耽误时间。
当第一个事件到达时,当前最大事件时间为 10:00,允许耽误为2分钟,因此水印初始值为 10:00 - 2分钟 = 9:58。
触发第一个窗口关闭的水印时间
触发第一个窗口关闭的水印时间为 10:07。
窗口关闭条件:当水印时间超过窗口结束时间(10:05)时,窗口关闭并触发计算。
允许迟到2分钟时,窗口会在原结束时间底子上额外等候2分钟。因此,实际触发关闭的水印时间为 10:05 + 2分钟 = 10:07。
事件时间 10:06 的窗口分配
- 当事件时间为 10:06 时,基于事件时间的滚动窗口(窗口大小5分钟),事件时间 10:06 落在 10:05 ≤ 时间戳 < 10:10 区间内,因此会将其分配到 第二个窗口,即窗口范围为 [10:05, 10:10)。
- 允许迟到时间(如2分钟)仅影响窗口关闭的触发机遇(窗口会在原结束时间后等候2分钟),不改变事件所属窗口的分配逻辑。例如:
- 窗口 [10:00, 10:05) 的关闭水印时间为 10:07(原结束时间 10:05 + 允许迟到2分钟)。
- 事件时间 10:06 纵然迟到,仍属于窗口 [10:05, 10:10),与允许迟到时间无关。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |