【原理】Flink如何巧用WaterMark机制解决乱序问题

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 【原理】Flink如何巧用WaterMark机制解决乱序问题

这是彭文华的第91篇原创

问:数据工程师最期望数据怎么来?

答:按顺序来。


MapReduce当初能用起来,就是因为Map阶段对所有数据都进行排序了,后面的Reduce阶段就可以直接用排序好的数据了。


批处理的时候因为数据已经落地了,咱可以慢慢排序。但是流式数据都是一条一条过来的,这个时候数据到达的时间和出发时的顺序不一致会导致非常多的问题,这该咋整呢?


Sparkstreaming对乱序支持很差,因为它其实是“微批”,不是真正的流。加州伯克利大学AMP实验室设计Spark的时候,想的就是弄一个更快的计算引擎,压根就没打算做成来一条处理一条的流式数据处理。所以对于一些乱序数据根本就不太关心,所以导致Sparkstreaming不能或者不太能支持乱序数据的处理。


但是Flink不行啊,数据一条一条的过来,然后进行窗口处理,乱序会导致各种统计问题,这就得必须解决了。


什么是乱序

一条数据在Flink里,有三个时间:

  • Event Time:事件产生的时间;
  • Ingestion Time:事件进入Flink的时间;
  • Window Processing Time:事件被处理的时间。

当数据一条一条规规矩矩的按流程发送,MQ传输,Flink接受然后处理,这个时候,就是有序的数据。

当出现各种异常,有些数据延迟了,排在后面的数据跑前面去了,这就出现了乱序。

请思考一下,我们应该以哪个时间戳判定乱序呢?


Flink的WaterMark机制

乱序会导致各种统计上的问题。比如一个Time Window本应该计算1、2、3,结果3迟到了,那这个窗口统计就丢数据了。这可太坑了。

为了解决这个问题,Flink设置了一个三个机制来解决这个问题:

  • WaterMark--水位线,;
  • allowLateNess--数据迟到时间;
  • sideOutPut--超长迟到数据收集;


水位线的设置很简单(系统时间为准):

override def getCurrentWatermark(): Watermark = {       
  new Watermark(System.currentTimeMillis - 5000)

设置Watermark为-5秒。但是怎么理解这个-5秒的水位线呢?


经常户外徒步的同学应该知道一个徒步小队通常会有一正两副领队,队首队尾各一个副队,正队长在队伍中穿插协调。

队尾的领队叫后队领队,后队领队要保证所有队员都在前面,也就是说后队领队是整个队伍的队尾,当收队的时候,看见后队领队,那就说明整个队伍都已经完全到达了。


这个Watermark就相当于给整个数据流设置一个后队领队。但是窗口是不知道具体要来几个数的,所以只能设置一个时间上的限制,以此来推测当前窗口最后一条数据是否已经到达。假设窗口大小为10秒,Watermark为-5秒,那么他会做以下事情:

  • 每来一条数据,取当前窗口内所有数据的最大时间戳;
  • 用最大时间戳扣减Watermark后看看是不是符合窗口关闭条件;
  • 如果不符合,则继续进数据;
  • 如果符合,则关闭窗口开始计算。


你看,多像户外徒步?

  • 每来一个人,就问问出发时是几号,然后确认所有已到队员最大的号码;
  • 用最大的号码对比一下后队领队的号码;
  • 如果比后队领队的号码小,就不收队;
  • 如果号码大于等于后队领队号码,就收队。


迟到的数据

当然啊,即便是用了Watermark机制,依然还会存在迟到的数据。就像户外徒步一样,有人走错路然后又赶上来。后队领队分明没超过任何一个队员,但是还是有队员落在后面了。


所以Flink还增设了三种应对方式:

  • allowLateNess--对于迟到一小会的数据,设置一个允许迟到时间;
  • sideOutPut--对于超过允许迟到时间的数据,全部收集起来,后续再处理;
  • 如果都不处理,Flink就默认自动丢弃。


也就是说,在watermark机制下,窗口虽然到了关闭时间,但是如果你设置了allowLateNess=10秒,那这个窗口还会再等10秒,看看是否还有他那个小队的数据,10秒后窗口关闭,开始计算。

如果等了10秒还没等到,11秒的时候,原本属于该窗口的数据才姗姗来迟,那么sideOutPut会把数据收集起来,放到侧输出流,等待后续处理。这个数据肯定就不会在当前窗口计算进去了。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
1月前
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
68 3
|
1月前
|
SQL 消息中间件 分布式计算
大数据-124 - Flink State 01篇 状态原理和原理剖析:状态类型 执行分析
大数据-124 - Flink State 01篇 状态原理和原理剖析:状态类型 执行分析
66 5
|
1月前
|
消息中间件 分布式计算 大数据
大数据-121 - Flink Time Watermark 详解 附带示例详解
大数据-121 - Flink Time Watermark 详解 附带示例详解
68 0
|
3月前
|
存储 数据处理 Apache
超越传统数据库:揭秘Flink状态机制,让你的数据处理效率飞升!
【8月更文挑战第26天】Apache Flink 在流处理领域以其高效实时的数据处理能力脱颖而出,其核心特色之一便是状态管理机制。不同于传统数据库依靠持久化存储及 ACID 事务确保数据一致性和可靠性,Flink 利用内存中的状态管理和分布式数据流模型实现了低延迟处理。Flink 的状态分为键控状态与非键控状态,前者依据数据键值进行状态维护,适用于键值对数据处理;后者与算子实例关联,用于所有输入数据共享的状态场景。通过 checkpointing 机制,Flink 在保障状态一致性的同时,提供了更适合流处理场景的轻量级解决方案。
58 0
|
1月前
|
消息中间件 监控 Java
大数据-109 Flink 体系结构 运行架构 ResourceManager JobManager 组件关系与原理剖析
大数据-109 Flink 体系结构 运行架构 ResourceManager JobManager 组件关系与原理剖析
65 1
|
1月前
|
存储 SQL 分布式计算
大数据-127 - Flink State 04篇 状态原理和原理剖析:状态存储 Part2
大数据-127 - Flink State 04篇 状态原理和原理剖析:状态存储 Part2
20 0
|
1月前
|
存储 消息中间件 大数据
大数据-126 - Flink State 03篇 状态原理和原理剖析:状态存储 Part1
大数据-126 - Flink State 03篇 状态原理和原理剖析:状态存储 Part1
59 0
|
1月前
|
存储 SQL 分布式计算
大数据-125 - Flink State 02篇 状态原理和原理剖析:广播状态
大数据-125 - Flink State 02篇 状态原理和原理剖析:广播状态
44 0
|
1月前
|
分布式计算 Java 大数据
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
33 0
|
1月前
|
消息中间件 NoSQL Kafka
大数据-116 - Flink DataStream Sink 原理、概念、常见Sink类型 配置与使用 附带案例1:消费Kafka写到Redis
大数据-116 - Flink DataStream Sink 原理、概念、常见Sink类型 配置与使用 附带案例1:消费Kafka写到Redis
131 0