00:00
我们已经了解了在flink当中基于时间的两种流操作,就是我们平常所说的双流join,它分为窗口连接window draw和间隔连接。那么它俩的区别主要就在于,一个是要开窗口,然后把窗口内配对的两条流里边的数据两两匹配,然后输出计算出最后的结果。那另外一种interval呢,它就没有窗口这一说了,只是针对某一条流里边的每一个元素。去截取它之前之后的一段时间间隔,然后去查找有没有另外一条流里边跟他匹配的数据,然后两两配对去进行计算和处理。那除此之外呢?这里我们再给大家介绍另外一种比较特殊的双流撞影操作,这就是所谓的窗口同组连接。它在代码当中的实现,其实并不叫做它叫做Co group,这就是所谓的window Co,那么整体来讲呢,它和前面我们介绍到的window draw是非常类似的,因为它都是基于窗口嘛。
01:12
都要有窗口的定义,所以在操作上其实也是两条流合并之后,然后指定每一条流里边的K,然后去开窗,然后去进行处理就可以了。所以在代码调用的过程当中,API的话只需要把之前我们介绍过的window drawing的draw替换成这里的Co group,后边操作其实都是一样的啊,这整个也都是定的API调用的顺序只能接下来就是然后指定两条流里边的K,接下来呢,就是点window去指定当前的窗口,接下来一个apply相当于后边传入一个窗口函数指定。两条流连接起来之后,匹配的数据怎样去做操作,那当然肯定还是跟window有区别。
02:03
最大的区别是什么呢?除了前面这一个调用的API方法名称不一样,那最大区别当然就是apply里边传入的这个函数类了。前面我们知道在window里边传入的是一个function,而这里呢,需要传入的就变成了一个Co group function。那当然了,这也是一个函数类的接口啊,那所以我们可以在源码里边看一看这个接口到底怎么定义的,就知道它跟window照应最大的区别在哪里,我们可以在代码里边,呃,之前其实我们知道window draw的这一段代码里边调用的是data stream里边的join方法,那其实我们直接看的话,会发现在data样也有1.coco。它也是传入一个get作为参数,然后得到的是一个Co group streams,那之前我们介绍如果是调draw方法的话,它得到的是一个join the streams。
03:07
Streams里边我们知道为什么它所调用的那一个规则啊,API就是按照顺序一个一个调呢,呃,点进去我们就会发现源码里边它只能接下来能调的方法就是V,然后呢,返回一个VR类型。这是一个在当前类内部定义的一个特殊的数据类型啊,特殊的类啊,那VR呢,里边又只能叫EQ two方法,其他就是都是一些,呃,就是对于这个比方说K的选择呀,或者k type的一些对应的一些方法啊,我们能够调用的就是一个e to方法,然后得到一个e to类型啊,那当然了,接下来e to就只能调用window方法,得到一个with window类型,With window,哎,那我们知道这就相当于得到了跟窗口有关的一个流,那接下来就要定义窗口操作了,所以我们看到它里边就可以调用各种窗口API,之前我们讲到的有一些其他API啊,A lateness al trigger这些都可以去调用,当然了,我们最关心的这些都是可选的,最关心的还是窗口函数,这里的窗口函数呢,就只有APPLY1种方法了。
04:17
我们之前介绍的是里边传入的是draw function,这里我们看到除了draw function之外,还可以传入一个flat draw function啊,那当然了,这个区别也非常明显,就像之前我们介绍map function和flat map function一样啊,那function的话。这里边啊,实现的这个装运方法啊,里边有一个抽象的装运方法,它就只有两个参数,分别代表当前两条流,里边匹配出来的元素作为参数传入,然后呢?啊,有一个alt类型的返回值,经过我们处理之后的结果就应该作为当前join的返回值返回输出,那对应的flat join方式里边我们就可以看到,哎,它就没有返回值类型,而是后边追加了一个参数,这就是我们所说的collect收集器啊,它跟Fla function里边一样啊,使用收集器的好处就是输出可以更加灵活,不需要每来一对数据都有一个返回值输出,我可以输出,也可以不输出,当然了也可以输出,多次输出就更加的方便了。
05:26
那如果我们还记得之前的internal的话,那显然这里边跟process draw function啊,呃,其实是非常类似的process draw function,我们可以认为它里边的这个process element方法可以认为就是一个加强版的。Fla function里的啊,所以我们看到它同样也是没有回值的类,使用了一个收集器collect去进行结的输出加灵活的输出,当然它的特点是还增加了一个上下文啊,所以它拥有了处理数process的一些特性,这是前面我们介绍过的。那现在的Co group方法又有什么样的特点呢?它跟前面我们介绍过的draw function或者Fla draw function process draw function又有什么区别呢?
06:13
呃,整体来看的话,它跟前面我们介绍的flat装方式其实是非常像的,我们可以看一下。当前调用了Co group方法之后,得到的是一个Co group streams,那同样它也是两个data stream啊,进行连接之后得到了一个Co group streams,那么对于这样一个数据类型呢,里边它跟joined streams非常的相似,也只能调用VR方法得到一个类型,然后调用e two方法得到一个e two类型,接下来调用一个window方法,指定窗口得到一个with window类型啊,那接下来又是窗口对应的API都可以调用了,最关心的apply。传入一个类似于窗口函数,指定怎么样处理两条流匹配的数据,那我们看到里边现在传的就不是装方式,而是一个Co group方式。
07:07
那么这个Co group方式呢?也是拥有单一抽象方法的Java接口,它的抽象方法就是Co group。那这里边呢,它的结构跟前面我们介绍过的。这是draw function,我们看到它跟draw function不太相似,其实是跟之前的flat draw function。比较类似,它没有返回值类型,而且后边有三个参数,用一个collector这样一个收集器进行我们当前结果的输出啊,那它跟Fla装修方式区别在哪里呢?主要区别其实在前面两个参数。Flax function前面两个参数我们说啊,这这就是input的,就是第一条流里的数据元素,第二条流里的数据元素匹配的元素没有一对匹配,那我们就调用一次当前的用方法进行一个结果的计算啊,所以如果我们回忆一下之前window这个这段代码的结果输出的话,我们会发现它其实是针对当前K和当前窗口里边。
08:14
所有的匹配的数据都会有。都会有一个两两配对的输出,比如说像之前我们这个第一个窗口零到五秒嘛,哎,那其实A这个。这个K对应的第一条流离有两个数据,第一秒和第二秒,第二条流里也有两个数据,三秒和4.5秒,所以我们看到最后的输出其实是两两配对的一个笛卡尔机的。配输出,所以它会输出四次,当前这个语方法就会调用四次,而现在如果是Co group的话,我们会看到它变成了一个类型。也就是说,当前并不是。窗口内的一个元素了,而是窗口内的一组元素,所有的元素放在一个集合类型里边,直接作为一个参数传入Co group方法啊,那对于当前同一个K同一个窗口的话,我们就知道了,每一条流里边的所有匹配数据都会由这个类型的集合收集起来,然后调一次Co方法。
09:23
啊,那就是所有元素都在这儿了,你想做什么操作都可以直接拿来输出就可以。所以我们会发现啊,用Co group。来进行两条流的双流draw影,那其实也可以实现之前我们做过的window draw影的这个过程,这window draw影相当于就是把所有匹配的数据两两配对拿出来了嘛,那我们现在所有数据都已经在这儿了,我当然就便利一下这两个集合一一去做一个匹配,然后输出一个笛卡耳机,匹配之后处理的结果就可以实现window撞影过程。好,那如果说我们对CQ比较熟悉的话,大家就会发现了,这其实就是CQ里边的内连接啊,应当的过程。
10:04
那当然了,对于window draw它是有缺陷的,它只能实现内连接。如果说我们在有一些。需求里边啊,不光想要得到它俩,就是每每一对数据匹配的这个结果,那假如说比方说当前窗口内我只有一条流璃有数据,另外一条流里没有数据,那相当于我当前这个窗口就没有任何匹配输出了,但有些时候我们还想希望让它没有匹配的那些数据,也就是我们说的落单的数据,也想让它有一个输出啊,也想看到,也想对它进行处理啊,这个时候怎么办呢?诶,Co group就可以进行这样的操作,所以它不光可以实现内连接,也可以实现啊,各种各样的外连接啊,左外右外全外连接都可以实现。所以我们可以看到,Co group应该是一种更加通用的window draw。事实上,在flink的底层,Window其实就是通过Co group来进行实现。
11:08
所以我们可以认为它是一个更加通用、更加底层化的window操作。所以接下来我们可以在代码里面。再去用一个测试的类来进行一个Co group的测试。那这个测试的过程其实我们就知道了,跟之前的window drawing非常的类似,我们还是把这个异常先抛出来,那既然非常类似,干脆我们的数据也不变了,直接用无draw这里边所有的数据啊,那就直接把这个代码都抄过来就可以了。当然了,这里边我们需要去做一个更改调用的API,调用的方法就不是join,而是Co group,那后边呢,当然apply这里啊,后面的VR这个定都一样啊,用我们当前这个数据二元的第一个元素作为当前的进行连接,然后呢,Window还是一样,指定一个五秒的滚动窗口,关键就是要改一下apply里边传入的这个类似于窗口函数的东西,现在不是draw function了,也不是Fla draw function,而是一个。
12:15
Co group方式,那这里我们同样啊,前两个它有泛型,前两个类型就是我们两条的数据类型,最后一个呢,那应该是输出的数据类型,我们还是作为一个。直接用一个字符串打印输出吧。接下来。就是实现里边的抽象方法Co group,这个也非常简单,因为所有的元素这是以一个or类型集合类型面部出现的,所以我们可以直接调它的to string方法,把它做一个打印。那这里就直接使用这个collector进行输出的时候调用点的方法。我们可以把first。加上一个箭头,这个我们用双箭头。再加上直接打印就可以了。
13:02
啊,那之前我们是两两匹配,匹配的每一个窗口内的所有数据,啊,两两匹配都有这样的一个笛卡尔机的输出,现在我们看一看同样的数据,如果做Co group的话,得到的是什么样的结果。这个我们看的就非常明显了,我们可以看到对于第一个窗口零到五秒钟,哎,我们知道第一条流里有一秒两秒两条数据,第二条流里有三秒4.5秒两条数据,之前我们输出了四条配对,调用了四次状方法,那现在呢?对于A来讲,只调用一次group方法。直接把这个集合全拿到了啊,那当然了,这里边我们如果想像之前那样输出四条数据也是可以的,我只要便利这两个集合,然后一一把它们匹配,对应的那个匹配输出就可以了,所以之前window能做的,现在Co也能做。
14:01
啊,那同样后边这个在第一个窗口里边B,那第一条流有两条数据,第二条留有一条数据,同样我们这里边也是直接输出一次就可以了,那对于第二个窗口五到十秒啊,这时我们是输出一条数据,那假如说现在我们是窗口里面都有数据啊,如果我们现在。第二条流里少了一条数据,那我们发现相当于只有第一条流里有数据,第二条里流里没有,如果在之前的window drawing里边的话,发生这样的事情的话,我们运行一下。那自然能想到,呃,就相当于第二个窗口就没有输出了嘛,我们会看到前面的这个5.1秒的B的数据没有任何的匹配,所以说没有任何的输出相当于丢掉了,那假如说我们还想让它输出怎么办呢?用Co就把它可以把它获取到。这个时候我们在一输出就会发现,即使后边这个second是空,那这个也会有一个空集合嘛,那这个时候还是有对应的输出的,所以Co可以看作是一个更加通用的,它可以实现各种内连接,外接。
我来说两句