00:00
好,那咱们呢,在思路一的基础上又发展出来的这个思路二,那这种方案是不是就是完美的呢?也不尽然。对吧,啊,也不尽然。呃,它不好的点在于什么呢?来注意看啊。注意看。这样吧,我把这个思路放在这啊,我们这样思路放在这,我我把图呢画在这个底下,哎,我把这个图画在这。大家呢,可以上面能看到思路啊,嗯,有没有可能会出现这种情况,什么情况呢,来注意看啊。他呢?是连续的访问。好。咱们的数据呢,是这样。OK吧,1234啊,这是两个不同的绘画,一二是一个绘画,三是一啊,然后呢,三四是一组绘画32,那再告诉我这个数据按照我们状态变成有没有结果。
01:07
就是如果说我是这样来的数据,对吧,那按照我们状态编程这个数据会不会有结果呀。看有没有结果。有没有结果?啊,这个要这么久时间吗?就是咱们有答案了,赶紧就扣一下,扣一下之后呢,我们就可以快点去往下一步进行对吧。我就非得等你们说啊。
02:01
就牛总一个人啊,说都不是跳出其他同学呢。按照我们这个逻辑,他有没有结果,还是真不知道,还是说又不想扣啊。他有没有结果?他会不会有数据输出啊,按照我们这个所说的。啊,有没有结果。啊,明总说没有结果。就这么不不愿意说是吗?啊,连个二都不愿意扣,一是确定二是否吗?好,这个显然是没有结果的哈,那如果说现在呢,我们出现了乱序呢。
03:00
他现在的数据是这样子的来的,本来我访问是按照1234对吧,现在呢,我是一。一。三。二。四我按照这个顺序来的,他有没有结果?我现在出现了乱序数据。他有没有结果?本来我访问的顺序呢,是1234对吧,但是呢。乱序。一四就跳出了啊有一三啊继续说。继续。啊,有说一三的,有说一四的,有说一的。
04:00
到底是谁?仔细想一想,按照我们这个逻辑啊,看这个,看这。到底是谁啊?11。11、三。还是一四。还是其他的?再仔细思考一下,现在大家的答案呢,都不统一。对吧,而且牛总还改了。对了,只有一啊。只有一,为什么呢?你按照这个走一呢。他上一条页面为呢,存到状态里边了,好第二条数据来三三呢上一条页面也为呢,所以一呢正常输出,好,然后来二二呢上一条阴面不等于呢不好意思,他就认为你俩是什么。
05:02
关联的对吧,你要关联的它这个呢,不能输出就要删掉对吧,定时器就要删掉啊好,那这个四呢,上一调也不等于呢,他认为这三条数据是什么。就是按照我们逻辑所写的,是不是认为这三条数据是一个绘画呀,对吧,因为他们的上一条页面怎么样。都不等于no对吧,所以呢,它会输出一个一,它呢没有结果,就正常来说它没有结果,但是呢,一旦出现了类似于这种乱序,它就有结果了。对吧,好,那也就是说咱们状态编程这种啊。解决不了乱序问题。对吧,我们想法挺好的,找这个上一跳页面等于那样的,但是呢,解决不了乱序数据问题。对吧,那一说这问题好,那咱们怎么办。好,咱回过头来。会话窗口可以解决乱序数的问题,对吧,那咱们呢,可以不这样写。这样太简单粗暴了,如果唯一,对吧,咱们能不能把这个思路变一下,还切回到会话窗口对吧?按照十秒去划分一个绘画窗口,但是呢,我呢,将。
06:10
窗口中的。所有数据按照时间。排序。对吧,按照TS排序,然后呢,挨个。对比对吧,对比什么呢?对比的过程就类似于是这个过程。对吧,我先看哎这条数据它。页面ID是不是那。如果是呢,我就保留下来,诶搞一个值给它记录下来对吧,然后看下一个,下一个如果是呢,我这个就输出对吧,如果下一个不等于呢,不好意思,这个呢不要,这个也就不要了。因为我按时间排序的。对吧,是不是这个逻辑能明白吗?就是我不简单的去统计为一,我干什么事儿呢?我把这个窗口里边所有的数据。
07:04
我排个序。我按照时间排序对吧,排序之后咱们做的事情还是这样。还是做这个事儿对吧,好,那判断上一条页面是否为呢,如果为呢,我就专门在外面搞一个值,把它记录下来,对吧,这边呢有个集合。电力对吧,电力这个集合好第一条数据,如果第一个它上一条文呢,我把它存到这里边,再看第二条对吧,看第二条,第二条如果说它也等于到。上一条ID也等于,那说明你挨着的,因为我已经排序了,它一定紧挨着的,对吧,他俩呢,是连续的两条,上一条为,那我就可以把它输出,把它呢写到这个里边,对吧,如果我接下来这一条它不是。他上一条不等于呢,那呢我把这个给它删掉对吧,这条数据呢,也就不管了啊,再看下一条吧,能理解吗。
08:09
能不能理解?对吧,我就不简单粗暴的去看这个一。啊,然后呢,我们就用这种方式。对吧,然后呢,我们是挨个比较,且呢用了会话窗口啊,而且我们可以用实件时间去开窗,他呢可以做到这个处理乱序数据问题,对吧?啊但是呢。这个代码就麻烦了,我们要挨个对比对吧,写一个循环去比较啊,里边把这个东西呢,都写到一起,而且呢,你这个窗口啊。还得用一个全量数据窗口吧,你得把所有的数据都保留下来啊,对吧,在我们窗口计算的,计算的窗口里边有两种,一种呢,增量来一条,计算一条,一种是全量,我得保存下来,对吧?保存在一个迭代器里边啊,那这个要全量消耗的资源呢,可能会更大一些。
09:06
那我们有没有更好的办法来结合这两者的。其实我们所需要的就是。状态编程加开窗对吧,如果能把这两个结合起来是不是就好了。对吧,如果我们能把这两者结合起来。是不是就好了,对吧?啊,因为那也就是说你光开窗没有看到状态编程啊,那我们在里边挨个遍历的时候,把第一条数据,如果为那把它保存下来,其实相当于用了状态编程的一个思想吧。对吧,我们有没有这样的一个操作呢,可以将。啊,咱们可以加。窗口。与。状态编程。结合起来的这么一个知识点呢,对吧,如果有的话。
10:01
那不就很nice吗?有没有?涉及到咱们那个什么呀。思路三啊,引出我们的思路三对吧,因为呃,思路二呢。它有瑕疵一定有瑕疵,但这个改了之后就会好很多,但是呢,它会麻烦一些,你呢要用全量。窗口,然后呢很麻烦,那我们三可以用什么呢?来我告诉你用这个啊,当然呢,也是针对于这个API的一个练习。叫CP。啊CP,因为CP这个东西呢,它本身就是一个状态编程。对吧,然后呢,我们再加上这个什么呢,它里边有一个关键字叫什么叫啊。叫vision干什么事呢,开窗。它呢,就相当于把这个状态编程跟开窗结合到一块儿了。
11:03
既可以处理乱序数据,又能维持我们这个功能。对吧,处理我们的复杂事件啊,这是我们的思路三,但具体的应该怎么写,我们下节课再聊,OK吧,引出来我们的CP啊,就是它呢,是结合着状态编程加。开窗操作可以处理乱序数据啊。注意CP是可以处理乱序数据的,对吧,而且呢,它本身也是状态编程所构成的啊。好,刚才呢,我们提到了,我们要用这个CP来解决当前我们的这个问题啊,一方面呢,是确实它可以。做到。状态变长。加开窗处理乱序数据。另一方面呢?我们也要练习一下这个CP。对吧,啊要练习一下,因为开窗操作呢,虽然我们后面不会去开这个会话窗口,但是呢,我们DWS会有大量的这个。
12:06
开窗啊,会有这个窗口操作,所以呢,我们就不用可以在这边去练习了啊好,那CP呢,它是处理这种复杂事件的,所以复杂事件呢,就是我们所说的叫。多个事件。对吧,叫复杂事件,因为F本身是来一条数据处理一条,来一条处理一条,所以它处理的呢,都是这种叫简单事件,那简单事件就单个的对吧,而复杂事件呢,就多个事件放在一起处理。好,那接下来呢,我们来看一下整体的实现思路啊,这个PPT还是一样的,我们给大家。整体的来。串一下。首先我们还是消费这个页面数据,因为我们还得用到上一跳。页面。为能对吧,还是得用这个条件啊呃,然后呢,要按照mi分组啊,之后呢,我们要定义模式序列,因为接下来呢,我们要用这个。
13:03
CPCP里边最重要的东西呢,模式序列,就是你要定义一套规则,你到底要找什么样的数据,对吧?你得把规则告诉我好,呃,那。我们来想一想,这个规则应该怎么定了,对吧?一块来想一想。就按照我们之前。所说的。对吧,状态编程里边能不能推出来当前这个。CP的条件就是第一个我们要什么数据。对吧。我们的模式序列里边第一件事情,我们应该用。什么数据?第一个事件我们应该怎么判断啊?就按照我们状态编程的条件来说,是不是应该找到上一跳?
14:02
为nu的数据啊。就是第一个啊,我们以上一跳为的作为开头吧。对吧,啊,那规则第一个对吧,我们取上一跳为none的,如果上一跳不等于呢,这个数据呢,那必然是不要的。对吧,啊好。那第二个事件呢?我怎么感觉现在这个直播间的弹幕上面,我感觉大家好像就没学过CP一样。鸦雀无声。就没有一个说话的啊,就是你们是没学CP吗还是咋的呀。还是怎么了?你们CP是没血吗?
15:00
而且CP是在flink后半段了。你学的很浅,我们用的也很浅啊。对吧,你不能说你学的很浅,我们用的也很浅啊,因为flink的使用很简单呀。弗林CP的使用很简单呀,它不难,对吧?我们用CP什么高深的东西了吗?没有啊,对吧,啊,那你看嘛,我们要的事情是不是这样子的,我们要找什么事呢,你看。是不是连续两个。我们要找的就是连续两个上一跳文档的状态编程里边不就这样做的吗?我还跟我刚才提示了,我说你想一想状态编程我们怎么去做,对吧。那第一个事件呢,我们必然要找上一条文档的,对吧?好,那第二个事件呢,是不是也找。上一条闻到的呀。对吧。啊,那第二个事件呢,我们也要找这个上一跳为囊的。
16:04
对吧,那如果说满足规则来看啊。如果说。满足了这个规则。那我们输出什么?就是我们发现连续的两条数据,它都是上一跳为呢。我就可以输出。输出什么告诉我。对吧,咱就可以输出第一个,第二个先不能输出啊,第二条数据得怎么样,得等第三条数据来,你得看第三条数据是什么样子的,对吧,输出第一个。对吧,好,那如果说那这个满足了。条件。啊,第一条数据,第二条数据呢,是挨着的,对吧,它上一条不等于呢,那这个呢就出不来对吧,它不符合规则,因为我们的规则呢,要连续的两个。
17:05
上一条文档的,但是呢,考虑到这里边有一种情况,什么情况呢,来看啊,这里边儿有一个情况是我来了一条数据。他是这样子的,但是呢,后面没有的数据,就这个mid。对于这个M而言,没有了数据,那你告诉我这个数据要不要输出。那怎么输出对吧,你。没有了数据,我要的是匹配两个事件,但是你只来了一个事件。是不是我们还有第三个规则啊,你告诉我第三个规则是什么?
18:05
哎,给他一个规定的超时时间,对了啊,这是我们今天说的,我们呢,第三个规则指定超时时间,对吧,防止什么呢?第一条来了。后面没有数据来,那这种情况呢,我们也要把它保留下来,对吧,而且呢,就把这条数据我们要的,而且给定超时间,大家还记得超时的这一部分数据放到什么地方。超时的这个数据放到什么地方,大家还记得吗?我估计应该。没什么人记得对吧。如果我们匹配的事件超时了,它是放在哪的?啊,测输出流对了。啊,没问题啊,就是放到测输出流的啊,所以呢,最终我们就知道了,把这两个作用作用到一起,对吧,形成我们的规则流,然后从规则流里边提取匹配上的事件,然后呢,取第一条,所谓匹配上的事件呢,就是两个都满足规则,这个叫匹配上的,对吧,我们取其一还有一个。
19:16
提取超时事件啊,提取超时件,因为超时事件呢,在测输出流。好,接下来呢,我们要把两个事件合并。把两个事件合并,合并好以后输出。输出到卡夫卡里边跳出明细就好了,对吧,这个注意啊,只要用了微,一旦发生了这种超时事件,对吧,那么他就是在哪呢?在。测输出流啊,他不是放在主流里边的,它是放在侧输流的,对吧,因为你是匹配上的,你是超时的,你两个人呢,不能统一而论,对吧?所以官方在开发这块内容的时候呢,它是分开放的,这很合理,对吧,万一你两种方式你都要,但是呢,你处理方式不一样的,他就没有放在流里边,对吧?但是最后我们可以合并到一起啊,我们用一个什么union,对吧。
20:10
我们用一个unit,诶把这个呢就合到一起了。对吧,跑到一起了,诶,这是我们所聊的这个用CP方式实现的一个。思路。
我来说两句