00:00
讲解了两种河流方式啊,这里是所说的是一个基本河流操作啊,一个叫做联合UN,另外一个叫做connect连接啊,其实大家会发现这两者的区别还是很明显的,UN其实就非常简单,它就是两个相同类型的流,但是它可以是多条流,多条相同类型的流直接放在一起,然后当成一个data stream用就可以了。而连接connect呢,就复杂很多了啊,它可以是两条类型完全不一样的流,然后连接在一起,一国两制去做计算。而更重要的是,我们可以通过KBY指定他们的K,然后让相同K的数据。放在一起去处理,哎,这个就非常的巧妙啊,因为在这个弗link里边KBY后边后续处理的时候,所有的处理都是只针对当前K嘛,所以如果要是两条流连接的时候,你做了一个KPI的话,那后边的效果就相当于是所有这里边我们的处理啊,特别是这个我们创建的状态state之前也说过,它也只针对当前K有效,哎,那这不就正好吗?这就起到了一个两条流进行连接的这样的一个效果。
01:10
啊,所以这其实对比我们在表处理当中啊,CQ当当中的处理,这其实就是一个状语操作啊,指定了K作为连接键啊,连接条件的一个状语操作,那呃,如果要说缺陷的话,那么connect呢,其实已经非常灵活了。只要是我们能想到的东西啊,你看它底层又有process function,又可以使用这个定时器,可以使用状态,可以说是所有的需求都能实现了,当然它也有缺陷,就是如果要做连接的话,只能是两条流连接,它不能像UN宁那样传多个流进来啊,这个也好理解,一国两制嘛啊,你就不能再一国三制了,对不对?你看那个接口都给我们定义死了啊,它就是process element1process element2,没有三了啊,它接口就那么定义,当然就是只能处理两条流了啊,这就是UN和connect的区别。
02:02
那在一些实际使用场景下呢,大家可能会发现union满足不了需求,因为union它这个太简单,两个流的类型不能不同,必须一样,而呢,Connect又太底层,大家会发现底层我们就是它只给我们提供了这个接口,就process element1 process element2,然后你要想做什么事情,那就都得去定义定时器,定义状态,这太麻烦了。有没有更加方便,更加简单一点的操作呢?有哎,那就是在弗link里边针对一些特殊的应用场景,提供了双流的连接操作啊,这个连接主要说的就是join join的一个翻译啊。那整体上来讲,其实状语大家可以理解成一种特殊的connect。啊,所以整体来讲的话,就是也是两条流的类型可以不同,但是呢,我现在希望基于时间去做一些特定的连接,把它们做一些匹配啊,找出对应匹配的数据,然后去做操作这种场景。
03:06
使用这个draw就特别的合适,所以我们把它叫做基于时间的河流。好,那接下来我们来给大家看一下。在flink里边提供了哪些特定的这种双流状的操作呢?一种就是窗口啊,我们知道时间嘛,啊,时间操作里边最重要的当然就是窗口操作了。那么对于我们如果说有这样的需求啊,两条流希望在一个时间段内,一个时间窗内,然后统计,按照某个条件啊,呃,然后去呃,比方说两个K相等的数据,我要连接在一起,去做合并,去做呃统一的处理,那如果是这种需求的话,那就正好可以使用这里的窗口连接。Window。直接给大家看一下这个窗口连接怎么调吧,其实整体来讲这个非常容易啊,大家看就是基于一个data stream直接调它的join影方法啊,这在源码里边。
04:08
The stream直接大家可以看到有一个状语方法啊,啊,那么这个状语方法得到的是一个Bo the streams跟前面那个connect是不是很像啊,Connect是调一个connect的方法,传另外一个data stream进来,得到的是一个呃,Connected streams现在呢是drawing,然后得到的是一个drawing the streams,同样它也两个泛型T和T2,那大家知道这就是一和二嘛,啊,然后这也是一个data stream,没关系的一个流的类型,但是它里边你看它是把这两条流data stream作为它的属性放在这了。然后接下来我们看它能调什么方法呢。它能调的方法只有一个来看,只有一个是where。那所以这个VR我们看的就更清楚了啊,那个两张表写一条CQ的时候啊,那个表1T1和T2啊,啊T1JOIN t2,然后当然一般T1如果直接写这个inner draw t2的话,后面应该是on作为条件,或者是我们用那个直接逗号分割,然后两张表放在一起的话啊,Select from t1T2逗号T2,然后后面不就是where什么等于什么吗?给一个这个连接键的条件吗?啊那所以这里边也是一样,Where后面就是一个kid select。
05:26
所以这个k selector,这又是,哎,大家看这和connect不一样,Connect k by是两个k select啊那就知道了,就是两条流里面分别提取K,然后他们要相等的放在一起嘛,那现在呢,现在只有一个啊,只有一个它是T1嘛,它就只是第一条流里边的K先指定。那第二条流呢?不要着急,它返回了一个类型,叫做where。而这个where又是个内部类,Where里边只能调一个方法,叫做e two啊,那么再看equal two,这里又是一个case select,调用已经是非常的直白了啊,就where什么等于什么嘛啊,所以就是前一个是第一条流里边的K的指令,后面是第二条流里边的K的指令。
06:12
然后接下来e to返回的呢,就叫一个eo to,一个内部类,那么这个e to啊,不只能调一个方法,就是window啊,终于来了,便把那个连接条件都指定好了,接下来要开窗了,然后window这里呢,看到里边传的就是一个window a sign。Window a sign的话,那这里这个a sign是我们之前窗口的那个操作里面的window a sign完全一样的,就是这个窗口分配器嘛,Aign Windows,所以接下来的这个操作里边可以定义滚动窗口,滑动窗口,会话窗口,哎这些就都可以去定义了。那当然了,这里大家会发现之前我们那个,呃,如果要定义技术窗口的话,是点count window对吧,这里直接就是点window,所以它都是基于时间的啊,这里是基于时间的。
07:01
那它返回的呢,变成了一个with window。这样一个一个类型。是一个static class,一个静态类,那这个with window又能干什么呢?这里边。最主要的能去调用的方法就是apply和这里边有loud lateness,不就是之前我们说的window的可选API吗?啊,另外还有avi,这不就是可选的移除器吗?还有trigger这些所有的都是以前窗口这个分配器啊,Window stream能做的那些事儿,现在他都能做,那当然了,我们知道最关键的可选的这些不重要啊,最关键的是后面你得跟端口函数。窗口函数是什么呢?这里只有一种,不是。点Fla啊,当然了,窗口函数具体来讲里边有两种,那就是要传的是一个o function或者flat draw function啊,一看这个flat,那你知道那就跟map和flat map一样吗?这里面区别就在于function啊,想到这个drawing function啊。
08:05
这里边有三个类型,他已经想到了,这跟那个home map function不是一样吗?INPUT1 input2 out啊,只不过里边呢,它只有一个方法叫做join,他把一和二都已经拿到了,然后直接返回一个outt啊,它是这样去去连接,就是把一组匹配直接拿到了,它不是像我们那样啊,就是还是两条流,一国两制,Connect里边是还是两条流的状态,它是直接把我们的一个匹配对拿到了,所以join是这样的一种处理方式。那另外那我们看到还有一个那个flat状语function对吧。Draw function区别在哪里呢?也是三个啊,INPUT1 input2out,那里边大家知道,就是没有返回类型,用这个collect去返回嘛,啊,这个其实效果都是一样的啊,这就是我们所谓的总结一下,来看一下这个调用的这个方法啊,到这儿的话,这就看的非常明确了,刚才我们也看到中间的每一步其实只能这么调。
09:05
啊,就包括最后一步这个window function,如果你前面这个不加其他的那些可选API的话,也只能调一个apply方法,只不过就是里边这个draw function可以换成flat draw function而已。所以。窗口连接。其实非常简单,它就是固定的用法,只能这么写。它这个套路就是这样的模板啊,就只能是这么去连接,就是一个流draw,另外一个流,然后where给一个K,就第一条流里面的K指定e to,第二条流里的K指定,接下来就基于这个K,两条流就连接在一起了啊,那接下来呢,就开窗,Window开一个窗,接下来就apply。告诉我们到底应该怎么处理这个窗口里边的数据,哎,那这里边大家可能会发现它其实就跟我们这个select from table啊,T1T2WHERE t1id等于TID,就是跟这种写法是完全一样嘛,那大家需要注意就是说我们当前的这个连接,就是如果说我们用这种方式去选取两张表,做两表draw应,然后选取数据的话,得到的是什么东西呢?
10:12
得到的是ID相等的啊,就是每一个元素它们两两之间匹配的那个状态,就一旦有匹配,比如说啊,我们这边有A1A2。这个数据啊,这是一张表对吧,然后另外一边我们如果有一个这个AB,比方说这个AB,然后啊BCD,假如说我们是以第一个字段作为K的话。那大家知道这个连接之后,这个效果应该就应该是得到得到什么,如果是select芯的话,哎,那就应该是AEAB。ARAB。内连接的话就应该是这样对吧?啊,就是如果那个找不到连接的那个key的话,那就那就没有了,那应该是把这个连接到的数据全拿到,所以现在window drawing呢,也是这个意思啊,就是只要你当前可以相等的,那大家想这其实这是一个假如说我们这儿还有一条这个A。
11:10
EF的话。那其实大家想就接下来还会有两条数据,对吧,AEEF。AREF。所以它其实是相同K的。对应元素的一个笛卡尔基对不对,每一个都会都会做这样的一个匹配啊,交叉有点像交叉连接之后的那种状态一样啊,只要匹配起来的数据两两都会配对放在这里啊,所以这是它的本身的一个含义啊,那大家可以看一眼官网上的这个介绍啊。可以看一下datapi对吧,Operators大家看一下这个drawing。官网上写的非常的明显啊,这里有几个图,我觉得大家应该看一眼这个图,应该就会理解的更加透彻了啊,那大家看一下当前应该有一个有一个绿流,有一个成流啊,这两条流要做一个照影,然后还是一个窗口照影啊,所以大家看这是滚动窗口啊,那当前这个它本身这是时间戳,那应该是按毫秒算的,因为你如果要减一的话,那就应该还是按毫秒算,两毫秒一个窗口对吧?那大家看这个第一个窗口里边是不是绿流和乘流都有两条两个数啊,0101对吧,那它得到匹配结果是什么呢?啊,就是00011011。
12:32
啊啊,就是笛卡耳机嘛,二乘二四种情况,这四种情况都会,都会到哪去呢?都会作为可以看到draw function里边它不是有first和second吗?哎,所以这里边只要匹配起来,在这个迪卡耳机里边匹配起来的这个00011011这四组数据。都会调用这个会。大家知道零零用状语的时候,那就是first是零,Second是零啊,那后面这个零一用状语的时候,First是零是一啊,就是这样的,每一组匹配到的数都会调用这个状语方法。
13:09
然后接下来大家看后边这一个框呢,数据少了一点,所以这里匹配输出到的就是2333,那大家这里就可以知道到底应该是谁在照应谁呢。因为他知道他有一和二嘛,First second大家看first是类型是印一,Second型是印二,First第一条流,这是第二条流嘛。哎,那之前其实我们知道跟connect一样,谁connect谁谁就是一啊,那现在join应也是谁照应谁谁就是一对吧?哎,那所以从这个角度看的话,2333,后边这个只有一个三,前面这个一呢,有二和三两种情况,那是不是应该是成流照影绿流啊啊所以大家可以看一下这个代码啊,这里下面就是这个具体代码,这个实现大家可以看到有一个orange stream和一个green stream,然后果然是成流去状语绿流啊,然后这个k select他就不写了啊,他知道就是让我们这个按照K分配就可以了,然后定义了一个滚动事件时间窗口两毫秒的啊,然后接下来apply,一个join function。
14:15
然后你看这里边它return first,它是return是一个string对吧,直接返回一个string就是first,然后加一个逗号second,所以这里不光是一个说明,这也是他真正输出的这个数据啊,就是当前这个窗口,它输出就是这个。啊,所以这就是这个窗口连接,那大家看到这个,这是滚动窗口的连接,那滑动窗口也一样,对不对啊,只不过就是窗口不一样了,收集到的数不一样了,只要是在这个窗口内的所有数都是这样的,一个笛卡尔基两两匹,对呃,然后去调用对应的这个状语方法就可以了。啊,那另外还有这个session window也是一样,只要在这个一个window里边把它框住的,两两配对起来去调join用方法啊,所以这个其实整体来讲啊,这个窗口状语还是非常简单的啊,我们会用这个最简单的例子测一下吧,看的能清晰一点。
15:08
好,那我们这里来测一下当前window join。Test做这个测试的话,我们用一下之前connect的这个例子。好,因为XQ的执行起来好把它放在这儿,然后接下来我们其实想要做的这个操作啊,就是直接能把它这个连接起来,有有一个东西就行了,但这里面又涉及到另外一个问题,就是这很麻烦,就是它是窗口连接得有时间啊啊,所以接下来如果说我们直接用处理时间的话,那那没意义,你这个处理太快,我们的处理时间窗口根本都到不了,时间就结束了啊,那所以这里边我们最好还是把这个对应的这个elements要稍微的改一下啊。改成什么呢?啊,直接就改成二元组吧,对吧,有一个当K,然后另外一个给一个时间戳就完事了嘛,啊那所以这个我们就直接借鉴这吧,大家看这个。
16:05
直接给一个A。1000B1000A2000B2000啊,那这里边我们得换成二元组类型,里边是一个string,一个long,一个长整型,除了这个之外,另外还有一部不要忘记,对吧,在time watermarks,我们直接copy。先把它copy过来。直接copy过来啊,然后接下来这里的这个类型当然不一样了啊,类型我们是这个二元组嘛。稍微比三元组简单那么一点。好可以过来,然后这里就。又一个好把这个创建出来,那这里当然就是这个零不能用这个啊element点F1。这是可以拿到的,那当然了,上面这个就要改成single output stream operator啊,这样的话,这样就比较看起来就比较合理了啊,然后接下来那那下面这个也是类似的一个状态,我们把这个copy一下吧,直接。
17:07
二啊。给一个stream,这样也是类似的这种这种东西啊,那这里稍微的改一改,比方说我们给个三四呃。啊,3445005500,给这么几条数据,然后接下来我们就考虑一下对它开窗进行一个测试啊,那接下来这个就是非常简单。先要照起来倒STREAM2。然后接下来,接下来大家看没什么好选的方法,必须是where啊,那我们就得用它的F0。然后接下来没有别的好选的方法,必须e to。负零都是他们的第一个字段啊,当然本身我们这里边定义的这个还是把它定义成一样了啊,那drawing function这个可以不一样吗?哎,当然可以啊,跟connect是非常类似的嘛,那比方说我们这儿换一下吧,把这个改成一个应记准对吧。
18:11
好把这个数据改一下,然后这来一个。那后面你还是让它自动生成一下就完了。省得我们很麻烦的去写啊。好,这里element点F1,这样的话看到啊,两个都是选取的F0作为当前的K,但是其实这两条流里面的数据类型是不一样的啊,那接下来我们看一下。To后边啊,只能window啊,能windowling even time Windows of啊,这个我们可以时间稍微的短一点啊,time.second一个一个五秒应该够了啊。然后接下来我们来看一下当前这个应该是apply啊,直接做一个apply,你有一个drawing function。
19:01
好,那看到就是最后我们输出的类型直接给一个string。边实现一个装修方法,这里边就是first,你看string long second string integer22匹配都可以显示在这里,那我们就看看它到底是个啥吧,对吧?First,然后加上。这个我们干脆就来来个箭头吧,对吧,来个箭头,然后看的。可以看到到底是长什么样子了。那最后我们来一个。就是我们整个这个,呃,测试窗口连接的这个代码啊,来运行一下你看。诶,大家可以看到我们当前得到的连接是什么样的呢?就是这个样子啊,啊,当然在这个draw里面,你会看到它不像我们之前的那个全窗口函数,这里边没有任何全窗口函数,对吧?这里边拿不到窗口的信息,所以能做的事情很少,你只能拿到对应的这两个数据,然后把它输出出来啊,就是连接在一起的,把它输出出来,我们看一下,呃,零到五秒肯定有一个窗口的啊,我们看一下这到底是什么,大家看一和一个三匹配到了一起。
20:14
这里是1122第一条流,大家知道是A和B对应的都有一个一和二的数据,一秒和二秒的数据,那我们看一下,那A那边有一秒和二秒的数据,所以就有一三的一个匹配和145的一个匹配,同样二也有二三的一个匹配和245的一个匹配,那B呢,呃,一秒和两秒就有一四的一个匹配和二四的一个匹配,那为什么没有呃到五五的匹配呢?因为这不属于五秒窗口了嘛。哎,那大家会想到,如果说上边我们这个运行的时候,再多一个比方说。多一个5100的话,那我们再运行一下。自然就会看到一个。
21:01
5100~5500的匹配对不对,诶,因为他俩是唯一的嘛,只只有他俩在第二个五秒到十秒的窗口里边能够匹配上啊,这就是我们对于窗口连接的一个测试。
我来说两句