文章目录
(一)WIndow与WindowAll区别
在前边的WindowAPI
调用时,我们发现不仅有Window()
,还有WindowAll()
,那这两者之间有什么区别呢?
Windows是处理无限流的核心。Windows将流分成有限大小的“存储桶”,我们可以在其上应用计算。
窗口式Flink程序的一般结构如下所示,分为键控流数据与非键控流数据,他们的区别正如您所看到的,唯一的区别是原始流是否进行了keyBy()
在上面,方括号([…])中的命令是可选的。这表明Flink允许您以多种不同方式自定义窗口逻辑,从而使其最适合您的业务需求。
总结:使用了KeyBy()算子后,数据流就会变为键控流;键控流应该使用window方法,未使用keyby()
的流(非键控流),应该调用windowAll方法
(二)有KEY 窗口和无KEY窗口
键控流调用window()
或者直接使用timeWindow()
、countWindow()
都是使用的有KEY窗口
(1)有KEY窗口
自定义有KEY窗口Function继承的的是RichWindowFunction
有key 窗口,作用在键控流基础之上,持有相同key数据会进入同一个窗口。有KEY窗口可根据并行度设置开启多个窗口,引用同一键的所有元素始终都将被发送到同一并行任务执行。(窗口计算会由多个subtask(根据并行度)执行,具有相同类型的key会进入同一个subtask执行。)
注意点:有KEY窗口会根据并行度开启对应数量个窗口,比如设置了并行度为4,那么只会开启4个窗口
具有相同key的数据会进入同一个subtask执行,但不代表一个subTask永远只会处理一个Key的数据,因为可能根据KeyBy后存在超出并行度数量的KEY, 那么超出的KEY仍会根据一定规则选择一个subTask执行,且以后一直由那一个subtask执行,只是说一个SubTask在处理当前KEY的时候会阻塞,当一个KEY的数据处理完了后,才会处理另一个KEY数据
(2)无KEY窗口
自定义无KEY窗口Function继承的的是RichAllWindowFunction
无KEY窗口,作用在非键控流基础之上,您的原始流将不会拆分为多个逻辑流,并且所有窗口逻辑将由单个任务(即并行度为只会为1)执行。
(三)有KEY窗口 无KEY窗口验证
(1)有KEY窗口执行结果示例
由于我设置了并行度为4,故此打开了四个窗口,且当前Job中,每个算子的并行度最多为4
打印说明:
打印语句前的 1 、3、4 可以视作为当前输出时(sink时)并行度线程编号,这个是从我们的sink输出方式print()打印出来的,1 可视为subtask1、3 可视为subtask3…
我们可以看到,subtask1输出了vehicleId=6的数据,后边又输出了一个vehicleId=4的数据,接着又输出了vehicleId=6的两条数据
subtask3接连输出了5条vehicleId=1的数据,然后下边还输出了一条vehicleId=4的数据…
比如 vehicleId=1、 vehicleId=0、 始终会进入subTask3执行计算逻辑; vehicleId=6 始终会进入subTask1执行计算逻辑
这就说明了,窗口计算会由多个subtask(根据并行度)执行,具有相同类型的key会进入同一个subtask执行。
(2)KeyBy-window-apply-sink算子链解释
哎!我就知道,直接看我这篇文章的朋友可能有点疑惑了!这明明是SInk打印的线程号,你咋证明Window和Sink 是用的一个线程呢?
答:因为算子链的机制,让KeyBy-window-apply-sink
组成了算子链(合为一个算子),组成后,就可以理解为KeyBy-window-apply-sink
是串行操作的了,那么既然是串行操作,自然window是啥线程执行,sink就是啥线程执行了呀!
详情请戳:Flink JobManger、TaskManger、TaskSlots、Client作用
详情请戳:Flink TaskSlot与并行度
请问各位小伙伴,当前这个Job会启动几个Task 几个subTask呢?
答:共2个task 共5个subTask; 一个task 是source(并行度为1 1个subtask),一个task是KeyBy-window-apply-sink
(四个并行度 则有4个subtask)
那明明我env设置并行度为4,为啥source还是一个呢?因为SourceFunction只支持单并行度,即使你env设置4,也不会生效!
直接上图为证!
可以看到,上方一共两个大Task 一个五个subtask,因为一个并行度中KeyBy-window-apply-sink
是串行操作,则window中的线程与sink线程为同一个
(3)无KEY窗口执行结果示例
上图示例可以发现,虽然我们的env设置了并行度为4,但窗口仍只是打开了一个,这就验证了无KEY窗口并行度只会为1;但是由sink的subTask数量完全受并行度影响,故此,sink仍会有四个线程同时执行;且没有同一个Key数据会进入同一线程限制,no-key-window计算后结果由哪一个sink-subTask执行,完全随机!
例如上图,vehicleId=2的数据,一开始被sink-subTask2
执行,下一次又被sink-subTask1
执行
问题又来了!按照此代码,我们当前Job会有几个task 几个subTask呢?
答:当前job执行时会有3个task,6个subTask;3个task为soure、no-key-window、sink ;6个subTask分别为 source 一个、no-key-window一个、sink四个
点击详情页查看