00:00
刚才我们在给大家讲这个进行事件时间语一下开窗测试的过程当中,大家可能会有一个疑惑啊,就是一开始我们说最先要关的一个窗口是。195~210对吧,那看到关的是195~210,那为什么第一个数据199来了之后,它没有触发这个窗口的关闭呢?或者说为什么不是第一个窗口,第一个数据来了之后,199从它开始,那大家想就应该是199~214,为什么不是这样的一个窗口设置呢?诶这个感觉就很奇怪对吧,为什么刚好是这个,呃195~210呢?诶那大家可能想到哦,像我们之前说那个一个小时滚动窗口的时候,我们都说是八点到九点,九点到十点,看起来都是一个整点整小时的这样的一个规划,那我们现在是15秒的窗口啊。啊,我看起来哦,那看起来好像是这个整五整十的一个数,对吧,195~210,那问题又来了,那为什么不是190~205呢。
01:07
这也是整五对不对。哎,所以大家可以猜测一下,这里边我们设置这个窗口的时候,它第一个窗口到底是属于就是我们当前开出来这个窗口啊,到底是从多少到多少呢?这是由什么来确定的呢。这个就涉及到了一个我们确定这个窗口之后啊,诶相当于在这里边是有一个窗口起始点的一个确定的,对吧?诶那关于这个窗口的起始点到底怎么去确定呢?诶我们可以看一下源码里边的这个行为啊,大家看一下这个,首先我们看到这个time window里边,现在我们是事件时间,当然掉的就应该是tumbling even time windows.off啊这这个大家都都已经回忆起来的话就都知道了,为什么叫做TM就呃tumbling even type Windows呢,就是在事件时间语义下的一个滚动时间窗口,对吧?啊就就跟我们当前的这个时间义有关嘛,呃,我们这个点window啊,直接默认里面调的这个东西啊window s是这个,好,我们点进来看一下。
02:12
这是一个window,它里边有一个。方法叫做assign Windows分配窗口,然后这里边它的参数是当前的element,这是不是就是当前的这个数据啊,传进来的数据,然后还有当前的时间戳,另外还有上下文。那最后得到的是什么呢?得到的是窗口的一个集合。也就是说,这一步是要干什么?这就是要确定对当前的数据到底属于哪些窗口,是不是就要开窗啊,诶所以大家注意啊,当前我们说这个窗口它并不是啊,就是我,但大家可能会想象,要不就是说一开始没有数据的时候,这个窗口就都开好了,哎不是这样的对吧?啊那要要要不就是大家可能想的这个这个数据啊,呃,就就有可能是每来一个数据之后都直接去开一堆窗口,诶那这里边比较近似于大家看到应该是来了数据之后开窗口的这个操作,对吧。
03:15
那要这么说的话,难道说这个199第一条数据来了之后开一堆窗口,然后201来了之后又开一堆窗口吗?这个这个最后他到底是怎么确定的呢?我们看一下里边的逻辑啊。其实这里面非常简单,就是判断,假如说当前的时间戳已经这个时间戳就是我们应该是刚刚那个数据提取出来的时间戳,对吧?已经有这个时间戳了啊,然后如果它大于这个我们初始的那个长整形最小值的话,那么就开始计算一个start,对吧?Start是不是就是当前窗口的起始点啊?所以接下来我们就要算第一个窗口,我现在要考虑的第一个窗口起始点到底是哪里?大家看一下后面,后面调用了直接调time window下边的一个方法叫get window start with offset。
04:07
诶,直接就掉了一个这个方法,当然这是一个静态静态的static方法对吧,所以就直接用类的这个直接调就完事了,这里边它有三个参数,大家看它的这里边的参数要求是一个时间戳time step,这是不是就是当前这个数据的时间戳啊啊当前它到底是呃什么时候发生的,对吧?当前这条数据什么时候发生的,然后后边呢,是一个offset偏移量。再后边是当前的。Windows当前的窗口大小对吧?啊,所以接下来这里边你看传的时候,也就是把这三个直接传过来了嘛,啊,然后在这里边大家看到这个return的时候呢,有一个固定的算法,有一个计算公式,这个看起来稍微有点复杂啊,有一大坨是吧?呃,首先我们划一下划分一下啊,它是基于当前时间戳来判断的,大家看到了是吧?基于当前时间戳,然后后面要减去一大堆,这一大堆。
05:06
直观来看的话,又是括号里边的一堆,是不是要对这个window size去模去模啊,然后里边的这堆东西呢,减offset offset,现在我们先不看先不管啊,因为一开始大家看到这个偏移量我们是不是都没设过,没设过默认是不是就应该是零啊,啊,这个很简单啊,默认就是零,所以接下来。那大家看就是time step要加上window size,然后再对window size取模,那这个其实大家能想到你加window size再对Windows取模,大家知道这个这个加不加是不是跟它没关系啊,大家知道取模的话,其实那个余数嘛,对吧,你如果加上之后,是不是相当于除它的时候的那个商会加一余数是不是不变啊,因为它本身它除自己肯定余数是零对不对,商是一,余数是零嘛,所以它俩,所以后面这一坨我们都直接先先去掉,先不看。
06:04
不看的话,接下来剩下的是什么,剩下的是不是就是。时间戳当前时间戳对window size取模,取一个除了之后的余数,然后在time STEM再减掉这个余数,那大家说剩下的是什么?是不是就是窗口大小,窗口长度的整数倍啊?大家想想是不是这样,你你说整个这个time STEM里边跟这个window size啊,窗口长度的大小的关系是什么?是不是就是它除以它有一个商,有一个余数对吧?那大家想我我在这里面直接把那个余数,这不是余数吗?全减掉了,剩下的是不是就是。本身Windows乘以商的那个结果啊,那是不是就是Windows的整数倍,哎,大家看就是这样的一个状态对吧?哎,所以大家就想到了当前我的第一个当前啊,第一个这个时间戳来了之后,199来了之后。
07:04
它是不是就按照这个规则去做一个计算啊,诶,那我这里面直接给大家开一个计算器来看一下啊呃,我们直接选取当前的这个199时间戳。啊,当然时间戳本身是一个呃长整型毫秒数后面加三个零的话大家知道呃,那接下来我们对于那个window size是不是这个,我们本来15秒嘛,那15秒是不是也得加三个零,那其实这个无所谓,对吧,我直接基于这个秒对15秒取余是不是一样的呀,对吧?那接下来取模mod Mo的一个15。多少?余数是?余数是不是四秒啊,四秒,所以按照公式是不是199再减去四秒,得到的是多少?是不是195啊,所以当时我们说第一个窗口是从多少开始的,195~210对吧。
08:05
呃,那大家知道这个滚动窗口嘛,第一个窗口一旦要是确定,那后面是不是所有窗口都定了,完全没有没有其他的可能了,对吧?啊,那一定就是195210,然后210225啊,所以大家会想到后边如果201这个数据来了之后,它取余结果应该是多少呢。大家觉得这个这个后面的数据来了之后,它不是也要调到这里面这个SM Windows吗?那这里面算出来结果应该是什么。我们把这个copy一下。这大家应该能想到吧,对,大家想201,然后是不是对15取模是不是六啊,201减六是不是还是195啊,因为大家知道最后算出来一定是是不是从零开始,然后零到15秒一个窗口,15秒到30秒一个窗口一点一点推移过来的呀啊,所以大家可以说按照这个规则的话,得到的那个起始点和结束点一定是15的一个整倍数,呃,15秒的一个整倍数,那相当于。
09:10
大家相当于这个这个算是不是我只是算当前这个数据属于哪个窗口啊,这个窗口是不是一开始就没有数据来的时候,我也知道这个窗口长什么样啊,对吧,一开始就可以都分配在那儿了,所以这就是我们说的窗口就是桶,就像桶一样,一开始就都放在那了,只不过呢,为什么199来了之后没有任何的窗口关闭呢。199大家知道来了之后我们延迟两秒钟,Watermark的话是1197 197之前要关的窗口,那大家想195~210是第一个窗口,那之前是不是应该是180~195啊,那这个窗口是关了对吧?197来了之后口是关了吧?嗯,但是里边有数据吗?啊,没有任何数据对吧?啊,所以呢,当然现在这个就最后,就相当于没有任何的输出嘛,所以后边继续来数据,我们最先有数据的窗口,要最先关掉的一个就是195~210。
10:10
就是这样确定出来的。啊,那既然提到这个,也捎带的给大家说一下这个offset啊,那大家可以想一下这个offset又是个什么东西呢。这是不是就是我们所谓的哎,就是有同学可能想到你像我统计的是这个,呃,15秒一个窗口,那按照这个规则一开始他就定了,你只能统计零到15秒,15~30秒,30~45,对吧,都必须是整倍数,那我就我就特别的膈应啊,我就特别的奇怪,我就想统计五到20秒一个窗口,20秒到35秒一个窗口,35秒到50秒一个窗口,你说这个叫不叫15秒的滚动窗口。也叫啊,它跟前面我们这种滚动窗口相比,只是它的那个时间戳不是15的整数倍,但其实也是15秒一个15秒一个头尾相接对吧,完全符合这个对它它的差别就在于起始点是不是偏移了一点啊,哎,所以大家看你如果想设置这样的窗口的话,用什么来设对加一个offset,诶,那这个offet大家就会看到,Offet就是在哪里定义的呢?这本来就是当前这个window aign里边的一个属性,对吧。
11:21
啊,那大家也看到了,这是不是在我当前的这个。创建的时候本身就可以有第二个参数啊,所以我们回到之前的这个,呃,这个啊,Window操作里边大家看一下,呃,就是在。我们还是直接点到前面的这个啊,Time window点到这里来。点这个of方法,大家看of方法本身这个它的构造方法是一个protected,所以我们需要调它的点of对吧,那点of这里边是不是只传一个窗口长度啊,哎,大家看这里边默认是不是就给调,调底下这个new的时候,是不是就给了opposite是零啊,那如果说我想指定opposite怎么指定?
12:06
传进来不就完了吗?大家看它还有这个,呃,重载的另外一个方法对吧,你看我可以传两个参数,这两个参数前面也是两个时间,第一个时间是当前的窗口长度,第二个时间就是一个偏移量offset。啊,那有同学可能说,哎不对呀,之前我们不是说时间窗口传两个参数的时候,这个第二个表示那个那个滑动不长吗。啊,大家注意这里边有滑动不长那一说吗?我们现在是什么窗口对大家注意啊,这就是当前我们用window a center的话,它里边是不是明确要指定你现在到底是滚动窗口还是滑动窗口啊,所以这里边如果是明确滚动窗口,那就不存在滑动补偿了,对吧?哎,所以第二个参数就一定是一个offset。那与之对应。大家能想到就是这里边啊,Time window,如果说我传两个参数的时候,这不是这个第二个参数是滑动不长吗?那里边儿底层调的是不是就是sliding even time Windows啊,调的这个这呃,我们这里边调到了它的of方法的话,如果要大家看这里边是不是也默认第三个参数是一个offset呀,所以自然我们能想到它也可以再传第三个参数,这个时候是不是就是滑动窗口的初始偏移量啊啊,所以这个都可以去设啊,Offset就在这里去设的。
13:27
那这个offset一般情况怎么用呢?这个有有人那么奇怪,比方说像我们这个,呃,本来一个小时的这个滚动窗口,对吧,你就非要统计8.05~9.05 9.05~10.05,你就非要这么去统计吗?感觉好好奇怪的样子啊,大家看一下这个一般是用来干什么?上面这个注释里边有非常详尽的说明,它一般用来干什么呀?诶,大家看一下这个大概看一下这个描述啊,它一般用这个偏移量来处理不同时区的这个时间。因为大家想到我们当前当前我获取自己的系统时间啊,啊,那我们当前应该都是北京时间,北京时间其实是东八区的一个时间,对不对,他跟我们处理的时候,直接获取的这个标准时区的时间戳啊。
14:15
是不是有所差别啊,大家知道标准的这个时间戳其实都应该是标准UTC时间,就是伦敦那个时区对吧?呃,格林位置时间啊,1970年1月1号零点开始的时间,那与之对应,我们这里边时间是不是比他们那边应该早八个小时啊?所以假如说大家想一下啊,我这里边要开窗口,我要开一天的窗口的话。大家想,如果偏移量是零,按照这个,呃,这个时间戳二整除下来,那是不是就应该都是整天的倍数啊,整天的倍数最后的效果是不是应该是伦敦时间的每天零点到第二天零点这样一个一天的窗口啊。那那对于我们北京时间来讲,我们这儿早八个小时嘛,他那边晚上零点的时候,我们这边是不是已经是太阳出来了,早上八点了。
15:07
所以大家如果开这样的窗口,你会发现我们这边窗口统计的每次都是早上八点到第二天八点,早上八点的这个时间段。那怎么办呢?我如果就想统计零点怎么办呢?给一个偏移量对吧,给多少的偏移量呢。哎,对,大家看给一个负八小时的偏移量,对吧,所以你这里边设置这样的一个窗口的时候,你看我可以给一个一天,然后后面给一个偏移量,Times hours负八。这就是这个偏移量的用法啊啊,这算是介绍这个窗口起始点的时候给大家扩展的一点内容,大家了解这个之后,测试的时候对它的结果就会有更深刻的理解了。
我来说两句