+[1 | 2021-11-01 00:01:03 | show_params | click_params]
+[2 | 2021-11-01 00:03:00 | show_params | click_params]
+[3 | 2021-11-01 00:05:00 | show_params | null]
如上就是我们期望的正确结果了。
flink web ui 算子图如下:
flink web ui
那么此时你可能有一个问题,结果中的前两条数据 join 到了输出我是理解的,那当 show_log join 不到 click_log 时为啥也输出了?原理是啥?
博主带你们来定位到具体的实现源码。先看一下 transformations。
transformations
可以看到事件时间下 interval join 的具体 operator 是 org.apache.flink.table.runtime.operators.join.KeyedCoProcessOperatorWithWatermarkDelay。
其核心逻辑就集中在 processElement1 和 processElement2 中,在 processElement1 和 processElement2 中使用 org.apache.flink.table.runtime.operators.join.interval.RowTimeIntervalJoin 来处理具体 join 逻辑。RowTimeIntervalJoin 重要方法如下图所示。
TimeIntervalJoin
下面详细给大家解释一下。
4.3.TimeIntervalJoin 简版说明
join 时,左流和右流会在 interval 时间之内相互等待,如果等到了则输出数据[+(show_log,click_log)],如果等不到,并且另一条流的时间已经推进到当前这条数据在也不可能 join 到另一条流的数据时,则直接输出[+(show_log,null)],[+(null,click_log)]。
举个例子,show_log.row_time BETWEEN click_log.row_time - INTERVAL '10' MINUTE AND click_log.row_time + INTERVAL '10' MINUTE, 当 click_log 的时间推进到 2021-11-01 11:00:00 时,这时 show_log 来一条 2021-11-01 02:00:00 的数据, 那这条 show_log 必然不可能和 click_log 中的数据 join 到了,因为 click_log 中 2021-11-01 01:50:00 到 2021-11-01 02:10:00 之间的数据以及过期删除了。则 show_log 直接输出 [+(show_log,null)]
Notes:
如果你设置了 allowLateness,join 不到的数据的输出和 state 的清理会多保留 allowLateness 时间
4.4.TimeIntervalJoin 详细实现说明
以上面案例的 show_log(左表) interval join click_log(右表) 为例(不管是 inner interval join,left interval join,right interval join 还是 full interval join,都会按照下面的流程执行):
第一步,首先如果 join xxx on 中的条件是等式则代表 join 是在相同 key 下进行的(上述案例中 join 的 key 即 show_log.log_id,click_log.log_id),相同 key 的数据会被发送到一个并发中进行处理。如果 join xxx on 中的条件是不等式,则两个流的 source 算子向 join 算子下发数据是按照 global 的 partition 策略进行下发的,并且 join 算子并发会被设置为 1,所有的数据会被发送到这一个并发中处理。
第二步,相同 key 下,一条 show_log 的数据先到达,首先会计算出下面要使用的最重要的三类时间戳:
经过判断,如果 on 中的条件为 true,则和 click_log 关联,输出[+(show_log,click_log)]数据;如果 on 中的条件为 false,则啥也不干
接着判断当前这条 click_log 的数据时间(r_time)是否小于右流的数据过期时间的最小值(r_expire)(即判断这条 click_log 是否永远不会再被 show_log join 到了)。如果小于,并且当前 click_log 这一侧是 outer join,则不用等直接输出[+(null,click_log)]),从状态删除这条 click_log;如果 click_log 这一侧不是 outer join,则直接从状态里删除这条 click_log。
第四步,判断右流的时间戳(r_watermark)是否小于能关联到的右流的时间区间上限(r_upper):
如果是,则说明这条 show_log 还有可能被 click_log join 到,则 show_log 放到 state 中,并注册后面用于状态清除的 timer。
如果否,则说明关联不到了,则输出[+(show_log,null)]
第五步,timer 触发时:
timer 触发时,根据当前 l_watermark,r_watermark 以及 state 中存储的 show_log,click_log 的 l_time,r_time 判断是否再也不会被对方 join 到,如果是,则根据是否为 outer join 对应输出[+(show_log,null)],[+(null,click_log)],并从状态中删除对应的 show_log,click_log。
上面只是左流 show_log 数据到达时的执行流程(即 ProcessElement1),当右流 click_log 到达时也是完全类似的执行流程(即 ProcessElement2)。
4.5.使用注意事项
小伙伴萌在使用 interval join 需要注意的两点事项:
interval join 的时间区间取决于日志的真实情况:设置大了容易造成任务的 state 太大,并且时效性也会变差。设置小了,join 不到,下发的数据在后续使用时,数据质量会存在问题。所以小伙伴萌在使用时建议先使用离线数据做一遍两条流的时间戳 diff 比较,来确定真实情况下的时间戳 diff 的分布是怎样的。举例:你通过离线数据 join 并做时间戳 diff 后发现 99% 的数据都能在时间戳相差 5min 以内 join 到,那么你就有依据去设置 interval 时间差为 5min。
interval join 中的时间区间条件即支持事件时间,也支持处理时间。事件时间由 watermark 推进。
5.总结与展望
源码公众号后台回复1.13.2 sql interval join获取。
本文主要介绍了 flink sql interval 是怎么避免出现 flink regular join 存在的 retract 问题的,并通过解析其实现说明了运行原理,博主期望你读完本文之后能了解到:
背景及应用场景介绍:博主期望你能了解到,flink sql 提供的丰富的 join 方式(总结 6 种:regular join,维表 join,快照 join,interval join,array 拍平,table function)对我们满足需求提供了强大的后盾, 这 6 种 join 中涉及到流与流的 join 最常用的是 regular join 以及 interval join,本节主要介绍 interval join
来一个实战案例:博主以上节说到的曝光日志流点击日志流为案例展开,主要是想告诉小伙伴 flink sql left join 数据不会互相等待,存在 retract 问题,会导致写入 kafka 的数据量变大, 然后转变思路为使用 flink sql interval join 的方式可以使得数据互相等待一段时间进行 join,这种方式不会存在 retract 问题
flink sql interval join 的解决方案以及原理的介绍:主要介绍 interval join 的在上述实战案例的运行结果及分析源码机制,博主期望你能了解到,interval join 的执行机制是会在你设置的 interval 区间之内互相等待一段时间,一旦时间推进(事件时间由 watermark 推进)到区间之外(即当前这条数据再也不可能被另一条流的数据 join 到时),outer join 会输出没有 join 到的数据,inner join 会从 state 中删除这条数据
总结及展望
大数据羊说
用数据提升美好事物发生的概率~
43篇原创内容
flink sql 知其所以然(十二):流 join 很难嘛???(上)
](mp.weixin.qq.com/s?__biz=Mzk…)
flink sql 知其所以然(十一):去重不仅仅有 count distinct 还有强大的 deduplication
](mp.weixin.qq.com/s?__biz=Mzk…)
flink sql 知其所以然(十):大家都用 cumulate window 计算累计指标啦
](mp.weixin.qq.com/s?__biz=Mzk…)
flink sql 知其所以然(九):window tvf tumble window 的奇思妙解
](mp.weixin.qq.com/s?__biz=Mzk…)
flink sql 知其所以然(八):flink sql tumble window 的奇妙解析之路
](mp.weixin.qq.com/s?__biz=Mzk…)
flink sql 知其所以然(七):不会连最适合 flink sql 的 ETL 和 group agg 场景都没见过吧?
](mp.weixin.qq.com/s?__biz=Mzk…)
本文使用 文章同步助手 同步