视频地址:https://www.bilibili.com/video/av53193640
一、Flink中的时间语义
1.Processing Time:
- 模拟真实的世界时间,本地机器时间。
- 处理结果不确定。因为每次处理的时间都是不同的
- 故障从savepoint 恢复,结果不同
- 本地时间只能递增,所以,数据在时间上一定有序,得到的是一个有序的数据流
- 典型:计算吞吐。现实一小时,处理了多少条数据
2.Event Time(Row Time):
- 数据中的时间戳
- 处理结果是确定的,多次处理,结果一致
- 故障从savepoint 恢复,结果相同
- 时间是绑定在数据上的,但是通常由于网络,分布式等原因,数据的到达可能存在一定的乱序
- 典型:过去一小时的某些指标的实时统计
二 、watermark
1.针对上面提到的,数据存在的乱序的处理方式
- 将部分乱序的数据充分的离散化,即将数据划分成一个一个的小段,虽然整个流是乱序的,但是划分之后,很容易保证,靠前的数据段的最大值 小于 靠后数据的最小值
- 然后在划分好的两小段之间,插入一个数值,此数值大于等于靠前数据的最大值,小于等于靠后数据的最小值
- 这个插入的值,就是水印
- 水印表示后来的数据已经再也没有小于或者等于这个水印所在的时间的了
2. Watermark 生成
- 在 SourceFunction 中产生水印(从源头产生)
a.源需要调用SourceContext中的collectWithTimestamp(...)方法。
b.为了生成watermark,源需要调用emitWatermark(Watermark)方法
override def run(ctx: SourceContext[MyType]): Unit = { while (/* condition */) { val next: MyType = getNext() ctx.collectWithTimestamp(next, next.eventTimestamp) if (next.hasWatermarkTime) { ctx.emitWatermark(new Watermark(next.getWatermarkTime)) } } }
- 有时候我们不想在 SourceFunction 里生成 timestamp 或者 watermark,或者说使用的 SourceFunction 本身不支持,我们还可以在使用 DataStream API 的时候指定,调用的 DataStream.assignTimestampsAndWatermarks 这个方法,能够接收不同的 timestamp 和 watermark 的生成器
3. Watermark 类型
1.定期生成器
-
- 现实时间决定
- 定期调用生成逻辑去产生一个watermark
2.根据一些在流处理数据流中遇到的一些特殊记录生成器
-
- 不是现实时间决定,而是一些具有特殊标识的数据自身决定
- 当看到一些特殊的记录,就表示这一批次已经全部接收完毕,然后调用用户自定义的watermark方法,去生成一个水印
4.Watermark 传播
1.首先,watermark 会以广播的形式在算子之间进行传播
2.如果在程序里面收到了一个 Long.MAX_VALUE 这个数值的 watermark,就表示对应的那一条流的一个部分不会再有数据发过来了,它相当于就是一个终止的一个标志
3.对于单流而言,这个策略比较好理解,而对于有多个输入的算子,watermark 的计算就有讲究了,一个原则是:单输入取其大,多输入取小
三、Table中指定时间
1.获取Table的两种方式
(1)可以从一个 DataStream 转化成一个 Table;
(2)直接通过 TableSource 去生成这么一个 Table;
本文深入探讨Flink中的时间语义,包括ProcessingTime与EventTime的区别及应用场景,解析Watermark如何解决数据乱序问题,以及其在算子间的传播机制。适合Flink开发者及对实时数据处理感兴趣的技术人员阅读。
1282

被折叠的 条评论
为什么被折叠?



