00:00
我们已经了解了弗link当中窗口的概念,那接下来呢,我们再来看一看在弗link当中窗口到底有哪些类型,其实我们之前说的呢,呃,都是时间窗口啊,首先在弗link当中,它不仅仅可以有时间窗口,还可以有别的类型的窗口啊,另外呢,在之前我们介绍的这个例子里边,当前这个窗口啊,都是最简单的时间窗口,就是我们看设置的这一个窗口的时间范围都是头连尾,尾连投,前面一个窗口结束了,接下来就下一个窗口就开启了,那其实呢,关于这个窗口时间的定义完全还可以更加复杂,所以接下来我们就来说一说在flink当中到底有哪些不同的窗口。首先我们先来说一下这个link当中啊,内置的窗口到底可以怎么样分类,首先可以按照驱动类型来进行一个分类,什么意思呢?啊,因为我们知道窗口本身就是我们在做数据处理的时候,截取有借数据的一种方式嘛,哎,那所以窗口的截取规则这就非常的重要了,就是按照什么标准去截取数据,我们就把它叫做窗口的驱动类型,最简单的方式,那就是按照时间嘛,啊就是当前这个数据。
01:11
看它的时间戳,多长时间内的数据,每一个时间段范围内的数据,我们都把它截取出来放到一起去,诶这就是这种时间窗的这种概念啊,那另外其实还有一种方式就是什么呢?那就是可以看数据的个数,我们可以数到底来了多少个数据,比方说我们这里可以要求每来三个数据,我就截取当前的一个窗口进行计算,这也完全是可以的呀,无界数据流里边截取有借数据,哎,那你当然是可以按照个数,也可以按照它分配的时间段嘛,诶所以我们按照这种方式的话,就分成两大类,一种叫做时间窗口。所谓的时间窗口呢,其实就是按照一个时间段来截取数据的窗口嘛,啊,那所以它里边最重要的属性其实就是当前窗口的时间范围,也就是说一个开始点和一个结束点,在flink里边呢,它本身代码里边,源码里边就提供了一个类,就叫做time。
02:12
那我们也可以看到啊,这个类它里边就有两个属性,我们可以看到一个长整形的start,另外一个长整形的and,这就是用一个长整型的时间戳来表示当前时间窗口的开始时间点和结束时间点。然后我们可以看到下面有对应的方法,可以get start get and,返回我们当前的起始点,结束点,另外它有一个方法叫max time step啊,它的含义是表示什么呢?就是表示当前窗口里边能够处理的数据的最大时间戳,所以我们看到它返回的是什么呢?是N减一,这里的一就是一毫秒,诶所以我们说啊,就假如说我们定一个八点到九点的窗口,它本身是包含八点整,不包含九点整。
03:04
前闭后开这样一个时间窗,那这个时候它里边能够包含的数据的时间戳最大到多少呢?其实就是到08:59:59。999毫秒,就是刚好没到九点钟的时候,这就是他的最大时间处啊,这就跟我们这个窗口的定义啊,左臂右开的定义完全一致。那这样定义有什么好处呢?我们可以结合之前watermark的特性,以及它跟数据时间戳的对应关系,可以来做一个分析啊,啊,那比如说前面我们说啊,来了一个。数据,比方说它的时间戳是十秒。那么按照我们之前的水位线生成策略,如果我们不考虑这个延迟啊,假如说我们当前就是有续流生续流,那么接下来它的生成策略就是直接在它基础上减一毫秒生成对应的watermark,那得到的watermark就应该是。
04:03
9999毫秒。前面我们说water mark的特性啊,Water t,那其实它代表的是小于等于T的所有数据都已经到齐了啊,那现在water mark进展到了9999毫秒,那也就是说在这一时刻之前的所有数据,时间戳小于等于9999的所有数据都已经到齐,都已经处理完毕了,当然时间戳就是十的数据,还有可能在后边继续到来。那这样对应在我们窗口操作里边是什么样呢?诶,那假如我们当前有一个零到十秒钟的窗口的话,我们知道前边包含它的左边界,不包含它的结束点右边界,那这个时候我们就知道当前窗口内的最大时间戳其实就是9999毫秒。哎,那所以小于等于9999毫秒的所有数据都已经到期,都已经处理完了,那当然当前窗口就可以直接关闭了嘛,啊,那所以我们会发现啊,经过这样的一个规定,经过这样的一个转换,我们其实就完全可以不考虑具体watermark生成的时候减一毫秒的这个影响了我们的操作,其实就是只要看到诶,当前十秒钟的数据时间戳是十秒的数据来了,那我就可以直接关闭零到十秒钟的窗口了。
05:23
啊,这个时候我们是不考虑延迟时间啊,乱续流延迟时间不考虑,那假如说是乱序流的话,我们延迟两秒钟的话一样,那我们就看到12秒的数据来了,直接减两秒钟得到的water mark是我们就认为是十,其实我们知道是十减一毫秒了,不管它到底是什么,反正我直接关闭当前零到十秒的窗口就可以了。啊,所以之后呢,我们就不再去详细讨论这个减一毫秒了,它对于我们关闭窗口其实是没有任何影响的,有时候我们可能就直接说啊,当前这个数据啊,12秒时间戳的数据已经到了,现在我们延迟两秒钟water mark进展到了十秒,可能就直接这么去说了。
06:04
这是关于这个,先给大家做一个说明。这是时间窗口的定义啊,我们在源码当中就有这样对应的一个泰尼类啊,那除了时间窗口之外呢,另外前面我们还说可以按照元素的个数去收集数据进行统计,开这样的窗口,那就叫做技术窗口count window啊,那count window呢,相对来讲就更加的简单一点啊,弗link底层也没有专门实现对应的类啊,我们就直接调用那个窗口相关的API去实现就可以了。它的底层其实是通过一个叫做全局窗口的类型来进行实现的啊,那关于全局窗口呢,这是另外一种分类方式,稍后我们再来讲。所以接下来呢,我们就来讲解一下另外一种窗口分类的方式,那就是按照窗口分配数据的规则进行分类,啊,那这是什么意思呢?那就是说,哎,像之前我们所提到的这样的一个时间窗口啊,它其实就是投连尾,尾联投,每一个数据只能分配到某一个窗口里面来,因为我们还是前避后开嘛,那现在我们就考虑了,那一个数据能不能被收入到不同的窗口里面去呢?完全是可以做到的,所以接下来我们要考虑的就是更加精细化的指定数据可以属于各种不同的窗口啊,那这种分配规则呢,就叫做按照窗口分配数据的规则去做一个分类。
07:29
那这样呢,窗口简单来说可以分为这样的四类,那就是滚动窗口,滑动窗口,绘画窗口和全局窗口,前面我们提到了,所以接下来我们就依次做一个介绍了。首先是滚动窗口,滚动窗口tumbling Windows,那这个其实非常的简单,它就是有一个固定大小,然后对数据进行一个均匀切片的窗口划分方式简单来讲其实就是头连尾,尾连头一个窗口结束,下一个窗口就开启啊那。
08:00
这里面每一个数据都会被分配到唯一的窗口里边,前面我们所介绍的那种窗口分配方式,其实就是滚动窗口。啊,那这里滚动窗口呢,我们只定义了数据分配的形式,并没有指定它的驱动规则啊,就也就是说可以有时间的滚动窗口,也可以有计数的滚动窗口啊,那所以如果是时间滚动窗口的话,那就是比方说我们每隔十秒钟。有这样的一个窗口啊,那也可以是。按照计数来,那就是每隔十个数有这样的一个窗口,这都是可以的。那比如说我们这里举的这个例子呢,很明显这不是按照数据的个数来分配的啊,这明显这是一个时间窗口,滚动时间窗口,那这里不同的user进行了一个划分,这是什么意思呢?很显然我们是按照用户的名称或者用户的ID做了一个K。所以我们会想到啊,那假如说批拜做了分组之后,然后接下来再开窗口是什么效果呢?诶,那就相当于是针对每一组数据,每一组数据都做了一个均匀切片啊,都是头连尾尾联投的,开了一个时间窗口啊,所以我们看到啊,当前的这个窗口操作,它就是针对单独的user去进行划分,去进行统计了,不同的user统计出来肯定是不同的结果。
09:25
那滚动窗口其实应用就非常广泛了,呃,很多情况下啊,我们的这个商业的分析指标都是基于滚动窗口去进行操作的。那在滚动窗口的基础上呢,还可以有另外一种扩展出来的窗口,那就叫做滑动窗口sliding Windows,它跟滚动窗口其实非常类似啊,那区别就在于它的首尾并不是相连的,而是窗口之间可以有重叠诶,那所以整体来看就是窗口的大小还是固定的,但是呢,它并不是头连尾,尾连头,就像整个一个翻身啊,一个翻跟头翻过去一样,而是一步一步的在往前挪,哎,所以我们就把它叫做滑动窗口。
10:09
有时候也会叫做跳动窗口啊,有时候叫做这个ho window,所以我们后面会讲到在CQ里边,它所谓的这个滑动窗口的实现啊,那个类本身叫做ho啊,那我们就知道它到底对应的是什么东西了。对于之前的滚动窗口而言,我们知道它其实没有什么好规定的,我们只要定义一个当前窗口的大小就可以了。诶,那大家可能会想到,那从什么时候开始呢?这个很简单啊,我们从时间出的零开始不就可以了吗?啊,默认从零开始,当然还可以指定一个偏移量,对吧?比方说我当前零到十秒,定义这个十秒钟一个窗口,那我就想从第二秒开始。二到12秒才是第一个窗口也是可以的呀,你定义一个偏移量就可以了,所以对于滚动窗口而言,我们最重要的参数就是一个窗口的长度,它这个固定的大小,而对于滑动窗口来说呢,当然我们也应该定义窗口长度固定的大小,另外它还应该多一个参数,就是当前。
11:10
滑动的这个距离,哎,我们管它叫做滑动步长,比如说我们可以定义一个长度为一小时,滑动步长为五分钟的滑动窗口,那么它代表什么意思呢?它就代表我们当前一直会统计一个小时之内的数据,然后呢,每隔五分钟就统计一次当前一个小时之内的数据啊,那所以我们就会想到最后的结果,那就是每五分钟输出一次。所以相比滚动窗口而言,滑动窗口的输出就会更加的频繁啊,所以在实际应用过程当中也是非常的重要啊,有一些对输出的频率要求比较高的需求,我们就可以使用滑动窗口去实现啊,那其实我们也看到了,滑动窗口其实就是。扩展版的滚动窗口,那对于一个滑动窗口而言,如果我们把当前的滑动不长定义成跟当前窗口长度一样,哎,就这个步子迈的有点大一步,就把它整个窗口的长度都划过去了,那我们看这不就变成了头连尾,尾连头就变成了滚动窗口啊,哎,所以滚动窗口我们可以认为就是一种特殊的滑动窗口。
12:23
那同样针对滑动窗口呢,我们也可以先定义当前的K,也就是做一个KBYKBY之后分组了之后呢,呃,再开窗,那我们收集到的就是当前组内的针对每一个用户,他当前时间范围内的所有数据啊,注意这里我们的这个WINDOW1看起来是框着所有的数据啊,其实并不是这样真实的应用,它其实是每一个user只统计自己在这个时间范围内的数据,得到一个输出,如果说我们把这个全部框在一起的话,那就相当于没有做KBY不分user,直接去开窗,那统计的就是所有数据。
13:02
滚动窗口和缓动窗口其实是我们在实际应用当中应用最频繁最广泛的窗口形式啊,那另外还有一种比较特殊的窗口叫做绘画窗口session Windows啊,那我们知道啊,顾名思义绘画嘛,Session它就是基于绘画来对数据进行分组的,什么叫做会话呢?啊,简单来讲,就像我们打电话一样,那就是如果隔一段时间我们不再去通话的话,诶,那就相当于我们认为当前会话已经结束,我们就可以截取一个窗口处理当前的所有数据了。所以它的标准呢,就不再是给窗口设置一个固定的大小,而是说,诶,我要去检测的是两个数据到来之间的这个间隔时间。诶,所以这里边它有一个最重要的参数,其实就是这个GAP size啊,就是如果说两个数据之间它的距离小于指定的GAP size的话,诶,那这个时候我们就认为它属于同一个窗口,如果已经超过了我们指定的这个size,那就相当于我们要划分不同的窗口了,所以这种方式它并没有固定的窗口大小,而且对于这个。
14:15
事件时间语义下的乱序流,诶,那我们可能会想到,就有可能会出现什么呢?我先来了一个数据,后面又来了一个数据,这个他俩之间的间隔超过了当前的GAP,那我们应该把它们放在两个不同的窗口里边,但是呢,啊,接下来有可能。中间还会到来一个迟到数据啊,诶,那这个时候有可能他就把这两个窗口就又连在一起了,诶,那所以呢,还会涉及到当前窗口的一个合并操作墨操作,哎,那所以这个呃,Flink底层啊,对于这个window算子的实现,它对于对话窗口会有单独的一个处理逻辑啊,这个会稍微的比较复杂一点。它的最大的特点就是窗口长度不固定,而且起始和结束位置也是完全没有规律的,另外还有一个特点就是口之间是一定没有重叠的啊,肯定每一个数据只会属于一个会画窗口啊,那同样它也可以针对我们当前的K做KBY分组之后啊,单独截取当前同一个用户某一个绘画里面的数据进行统计。
15:20
这就是所谓的绘画窗口啊,那最后还有一类窗口,就是前面我们说到的啊,实现技术窗口,底层的全局窗口,什么叫全局窗口呢?它其实就是一个比较通用的窗口了,那这种窗口呢,顾名思义就是全局有效,换句话说就是假如我们做了K的话,那就会把相同K的所有数据全放在同一个窗口里面来。啊,那我们就会发现啊,它就是就跟没分窗口一样,根本就没有结束时间,哎,那所以默认情况下它是不会去触发计算的,所以如果说我们希望他能对数据进行专门的处理的话,还要自定义一个触发器trigger啊啊,那关于这个触发器呢,我们会在后边再做具体的讲解,那对于前面我们介绍到的技术窗口,它其实就是单独的给我们实现了一个技术的触发器,然后按照数据个数做了一个窗口的划分。
16:19
这就是关于flink当中窗口的不同分类。
我来说两句