00:00
啊,接下来我们已经了解了水位线,那我们再来看一看窗口到底是什么东西啊,那其实在大数据应用,我们做这个数据分析统计的时候,基于时间最常见的操作其实就是窗口,而前面我们讲这个事件时间,所有的这个测试可以运行,但看不到什么结果,因为它只是只是了一个时间,那你这个时间有什么用呢?要干什么呢?你总得用它来控制点什么东西吧?诶,那所以最典型的一个利用时间来控制输出的场景就是窗口,时间窗口,那接下来我们就来探讨一下这个flink里边窗口的含义,那提到窗口呢,其实那完全不陌生啊,在Spark里边都接触过啊,都知道有这个窗口,那Spark里边的窗口到底应该是什么样子的呢?哎,那简单来讲的话,其实SPA streaming里边有这个窗口,那我们就是一组数据啊来了。然后如果说我们基于它要开窗的话啊,那我就是直接在这开个窗嘛,这窗口里边啊,框住了三个,那个窗口里边数据就这三个做计算了啊,然后后面又一个窗口,诶框住了这三个,那就把这三个数据做一个计算,大家所理解的窗口应该是成这个样子,这是大家常规的理解。
01:14
但是接下来我们要给大家介绍的flink里边的窗口呢,可能会更新一下大家对窗口的理解,在真正的流里边,窗口的含义其实没有那么简单。我们这里先给大家说一下,在flink里边窗口到底是一个什么地位啊?我们都知道link是一个可以处理无限流的流失处理引擎,那无限流有一个特点,就是数据无休无止,源源不断。啊,那之前我们也看到了,假如说我们把那个click s那个圆开启起来之后,只要你不停,那我们这里的这个数据会不停的读,不停的读,那你如果要是想做一个聚合,想做一个统计的话,那之前的那个reduce大家也知道啊,K之后reduce每来一个数据就会输出一个结果,每来一个数据就会输出一个结果,那什么时候是个头呢?
02:03
那永远没有镜头,而且是永远在不停的更新啊,那这种情况我们很烦啊,我不能最后只看一个结果吗?比方说我就想收集一天的数据,昨天的数据到今天的数据,那这样的话,我们就其实是人为的给这个无限流,无限流。增加了一个界限,增加了一个范围,这其实就是把无界流切成了有限的数据块,这不就是有界流吗?那如果要是用在我们具体的API操作上,有限的这一个数据块其实就是一个窗口。这个窗口里面可以包含很多数据。所以在弗link里边,窗口其实用来处理无界流的一个核心,往往我们都不会就像之前那样要做聚合,直接就所有的数据直接来一个聚合,一次来一个聚合,一次源源不断的更新,这种情况其实比较少见,更多的都是哎,我们统计一天的数据,一周的数据,一个月的数据啊,这样的话就可以直接去做进一步的统计分析了。
03:07
啊,那一般情况我们认为这个窗口呢,既然说窗口嘛,那外围应该是有一个窗框,本身是一个框,然后这个框框到多少的数据啊,那这个窗口里边计算的数据就是这些了,然后呃,如果是到点的话,窗口开始要出发的时候,比方说八点到九点这个窗口啊,那就是八点钟这个框就打开了。然后呢,就一直往后延伸,往后延伸到九点的时候,框截止啊,那框住多少数据就算多少数据,这大家比较熟悉的这种用法啊,这里边就会有一个问题啊,我们的这种做法,如果说在处理时间语义下,那是没毛病的,因为我们知道系统时间当前是多少就是多少嘛,我说一个开始好,那开始框说一个结束好,框柱多少就算多少,但是现在我们是事件时间呀。那假如说在事件时间语义下,它是不是会有这个乱序的情况出现啊。
04:02
而且就是说在事件时间语义下有乱序时间的话,我们之前不是说有这个watermark可以去做这样的一个优化,把它乱序的时间多等一会儿,让他收集齐吗?想要等那个更新的数据的时候,那不是更大的数据也会收进来吗?比方说大家看一下当前的这一个图,我们考虑的是十秒钟一个窗口。零到十秒的数据想要收到这个窗口里边来,假如你还是一开始零秒的时候,开始一个框,然后就开始往后延伸,往后延伸,然后呢,等到十秒的时候截止啊,那你就一直往后了,一直往后所有的数据都在里边,九秒来的时候,如果说我们还是之前延迟两秒的乱序数据的触发机制啊,Water mark触发机制的话,那九秒后边water mark到多少呢?延迟两秒,那应该是到期了。啊,那如果到期的话,当然零到十秒这个窗口不该关啊,这个肯定是不关的,那接下来11就来了。
05:02
11来了之后,大家知道它已经不属于这个窗口了呀,但是你窗口还不关,诶那我就继续延伸喽,继续往后延延延,然后九秒又来了,诶果然乱序数据嘛,诶后面他又来了,我正常收进来了,然后来了一个12,现在water mark在它后边,我知道了water mark到十,现在该关这个窗口了,但是大家看你要这么去截取的话,拿它去框的话,这框出来的数据,这不是11跟12都进来了吗?你是正确的处理了迟到的数据,迟到的这个九是进来了,但是早到的11跟12就放到这儿来了,这不是还是不能正确处理吗?又变成错误的一个结论了吗?这个大家就要更新一下我们的这个对于窗口的理解啊,窗口其实不是这样的。为什么呢?因为我们说了对于事件时间而言,没有找到的数据这一说。啊,就是你如果已经11秒的数据已经来了,它发生的时间就是11秒,那肯定事件时间已经进展到这儿了,所以只有在它之后,如果要有时间戳更小的数据来的话,这是迟到了,你不能说11秒是早来了,他不该来,所以呢,我们的处理机制应该是什么样呢?你不要这样机械的把所有这会儿来的数据全框在这个里边,按照顺序框在里,而是应该怎么样呢?按照它本身的时间戳。
06:22
去判断它到底应该属于哪个窗口,因为我们现在就是实线时间嘛,它的时间戳都已经告诉你了,那你怎么还要硬把它分到这个零到十秒这个窗口来呢?哎,所以接下来我们对窗口的理解就是。要把它看成框,而是把它看成一个桶。看成一个bucket。这是link里边就是明确提出的一个概念啊,就是你把它看成bucket,看成bucket之后这个效果就变成什么样了,看这张图。呃,一开始啊,零秒的时候啊,第一个数据来了,二来了啊,那我开了一个窗口,这个零到十秒的窗口打开了,它是一个桶,二来了之后塞进来,哦,现在后面如果要有water的话,大家知道延迟两秒,这是零秒嘛,然后五来了,Water进展到三,那还是五就放进来,窗口没关嘛,九来了,我从rock进展到九,哎,没关,继续放进来,789继续都扔进来,11。
07:19
来了之后要注意这里的water mark是九。零到十秒窗口关不关呢?诶当然不关了,你没到时间的嘛,那11扔到哪里去呢?诶当然不应该在这个窗口里啊,那这里我既然已经知道它是11了,那一判断就判断出来它应该属于下一个窗口。十到20秒,哎,那既然来了11,那我就把这个窗口,这个桶也创建出来,把11丢进去不就完事了吗?哎,所以窗口是可以同时有多个的。谁告诉你同一时间只能有一个窗口呢?我们把它当成桶的话,这个就很好理解了,所以11扔进来,那后面又来了九九怎么办呢?哎,再扔进前面的这个桶来嘛,然后又来了一个12 12首先是判断它属于哪个窗口,那它是属于这个窗口,属于第二个窗口塞进来,然后呢,在他之后的water mark现在变成了十,变成十怎么办?
08:15
关闭第一个窗口。所以第一个窗口,在这之前所有的数据就都收集齐了,完全正确的收集齐了。然后继续,如果后面再来的话,不会再来十之前的数据了,按照我们那个watermark定义就不会再来了啊,那当然你这个窗口关,关就关了嘛,数据就是正确的,所有前面来的数据都收进来了,而且也没有把后边不该收进来的数据放进来,而且后边也不会有迟到数据丢掉了,所以我们现在的处理就是彻底正确的。这就是窗口真正的处理过程。所以那个里边窗口并不是静态都准备好了,不要认为是这个一个框框在那儿就完事了,它是动态创建的,有一个数据来了之后,落在这个范围内了,我们就创建这样一个统,那另外这里就是说到达窗口结束时间的时候呢,我们这里说的就是关闭窗口,那其实它这里边要执行的操作是什么呢?是应该要把当前窗口做的那个统计计算要完成,然后朝下游任务输出一个结果,然后再清空状态,关闭窗口,其实这样的一些操作,那事实上对于窗口而言,触发计算和关闭窗口这两个是两个不同的操作。
09:31
它是可以分开的啊,只不过在现阶段我们姑且认为它是一回事,就是你之前数据都是先收集进来啊,然后我是到了要窗口结束的时候,我才去算一下输出结果,然后把这个窗口关掉,我认为这是一回事。但是大家知道,这两个其实可以分开的。这就是关于窗口的基本概念。
我来说两句