00:00
学习了窗口函数里边非常重要,或者可以说是最重要的一类吧,就是体现了流处理特色的增量聚合函数,那里边最为通用的就是aggregate方式,所以这个应该作为大家掌握的一个重点。另外我们知道就是弗link为窗口聚合提供了很多预定义的简单聚合方法,这个跟KBY之后的那个聚合是一样的,萨max mean max by mean by,呃,那么他们底层其实都是aggregate function,通过aggregate function来实现的,这就是我们窗口聚合增量聚合的一个核心机制。那除了这种方法呢,二大类就是所谓的全窗口函数window functions,那么全窗口函数它其实它这个特点跟增量聚合函数就是完全相对了,增量聚合函数如果说是流处理的思路,来一个就聚合一次,来一个就聚合一次,那么全窗口函数就是彻底的批处理了。所有的数据来了之后,就在这儿等着,先攒起来,等到最后要去触发计算的时候,统一安排,把数据提取出来,你想做什么做什么啊,那它的这个意义到底在哪里呢?在有一些场景下,可能我们最后想要去做的这个计算,它必须就是所有数据到齐了之后,对应的这一个信息才是比较有效的啊,比如说之前我们是那个求平均数啊,平均数的话,我们还可以用呃萨姆和这个个数两个聚合字段来最后做一个计算,那假如说我们想要算的是。
01:33
分位数呢?假如我们想要算一个这个数据的中位数,呃,就是中位数的含义是相当于所有的数据要做一个排序,然后我去选取50%这个位置的那个数到底是多少,这个在有一些统计数据里边,其实比均值的含义是要更加重要的,所以有些时候啊,这个东西就是可能你需要知道所有的数据才能得到的一个结果。弗link给大家提供了这样的一种方式,就是你可以把所有数据都攒齐了,然后最后再处理。
02:06
啊,那所以这就是所谓的全窗口函数啊,全窗口函数呢,主要也是有两种,一种它的名字,这个类名啊,就叫window function啊,或者这个应该叫接口名对吧,接口名就叫window function,而另外一种呢,叫process window function。大家会看到啊,这个叫窗口函数嘛,看起来这是一般化的一个窗口函数是吧,我们说这个整个定义窗口计算的这一套东西就统一都叫呃window function,都叫窗口函数,这个是广义的window function,那这里还有一个狭义的window function,其实在弗Li啊,最初它定义这个window function的时候,就就定义的是这玩意儿,就他就认为就是把这个东西都收集起来,然后你你去做一个计算嘛,对吧,定义这个窗口要做什么计算,自己去定义不就完了吗?啊,所以这是最初的那个模型,但是这个呢,它其实不如那个增量聚合好用。如果说你想要拿到更多的信息呢,诶,这里就又提供了一个process window function啊,就是说这个window function它能拿到的是什么信息呢?主要就是拿到窗口相关的,和K相关的一些信息,而process window function呢,它还有一个process。
03:16
大家就看到了这个更高级,为什么更高级呢?这是我们之前所说的process function处理函数的一元,它是一个底层API,所以他能拿到的东西更多,不光是能拿到像窗口的信息,K的信息,他还能拿到比方说当前的水位线到底在哪里。比方说他还可以去做我们当前的这个时间相关的一些操作,那这些东西它它都是可以去进行处理的,所以现在的版本啊,最新的版本window function基本上就要被弃用了啊,就是现在一般是不推荐大家直接用这个window function,直接用这个process window function可以全覆盖它的功能。啊啊,那这里我们简单还是说一下吧,就是如果大家见到有代码里边写这个window function的话,也要知道怎么用啊,它这里边调用方法就是点window,然后后面是一个点。
04:10
Apply。啊,Flash应用的意思嘛,应用一个window function,所以大家看这个就是非常通用化的这个这个语义啊,如果翻译过来,其实是最为普通的窗口应用,窗口计算的这种操作,然后里边你就要去实现一个自己的window方式,Window方式里边有一个参数给大家源码看一眼。呃,我们直接去看当前这个方式。大家看运动方式里边有四个方形。Input,当前的输入output输出,还有K,哎,这里还有当前K的信息,对吧?当前的K到底是什么?另外还有w w window,当然就是当前window的类型了,Window的信息也有啊,这就是当前这个window方式,那怎么没有中间那个累加器,没有中间的聚合结果了呢?所有数据都攒齐了。
05:03
那就没有中间状态了,你想怎么做怎么做,因为它不做中间的累加嘛,啊,所以这就是一个in,一个out啊,然后里边要实现的方法也非常简单,就一个apply apply参数呢,有key有window都可以拿到,另外大家要注意啊,这个out,那这个跟我们之前那个Fla map都一样,就是用这个collect去做数据的输出,out.collect方法去做数据输出,那比较特别的是看一下这个input input是一个。硬类型输入类型的interable啊,可迭代集合对吧?啊,所以这其实就是把所有的数据都攒到一个集合里边来了嘛,啊,你接下来就是从这个集合里边获取数据,想干什么干什么,最后包装成输出就可以了。还可以结合窗口的信息和K的信息啊,这个是window function啊,很简单,呃,那它的使用呢,我们也就不专门讲了,因为现在基本上都用这个process度方式啊,它其实跟这个温度function的应用也非常的类似,我们可以这里边看一眼啊,这个我们就直接用一个代码来说明吧。
06:09
直接来一个win process。首先还是前面的这些内容要抄过来。然后后边en nv XQ这个不要忘记。空间的内容,那就是开窗做处理了,不能叫聚合了啊,当然也我们也可以说这是广义的聚合对吧,因为你最后的处理肯定是把数据想要得到一个什么结论嘛,但是未必就是聚合啊,就是未必是要合并成一个值啊,有可能是多个值,有可能是排序,所有数据还要输出啊,这都是有可能的啊啊,所以它其实就是一个数据的处理计算啊,那基于当前的这个stream,首先我们可以去做一个K。那这里我们还是想一个具体的场景吧,就还是用之前的这个UV吧,我们还是做一个这个UV的计算好了。
07:02
只用。Process window function。计算UV。因为大家知道UV的话,其实就是要做驱虫嘛,那我也也可以把所有数据都攒齐了之后,然后再一个一个拿出来去做一个叠加判断。啊,那这里边就是既然是和这一个UV的判断,那其实前面还是所有数据都要放在一起,对吧?啊,那这个过程其实跟我们前面的那个实现是非常类似的啊window这里我们简单一点就是一个滚动窗口吧点嗯。因为滑动窗口前面我们已经测过了啊。然后接下来就是到一个,那我们说普通的window function调的是apply方法,那现在如果是process window function呢,调的就是。方法。然后接下来里边要传的就是一个,看到要传的是一个process window function啊,那这个我们还是。
08:05
不读的,在下边把它做一个实现吧,因为这个可能会稍微复杂一点啊,这边我们实现自定义的process window function。那我们主要想输出个啥呢?这就是想要输出这个UV,干脆输出一句话吧,输出。一条统计信息就是一个string。主要的内容应该包括当前的窗口是哪个,然后它的呃,UV值到底是多少啊,其实就是主要是两个啊,一个就是窗口是谁,然后UV值是多少,就这样的一个信息,你想把它包装成这个二元组也是可以的,只不过我们这个呃窗口信息还涉及到。可视化的一个表达,对吧,你把它弄成那个time,然后打印成年月日十分秒,这样的话我们就用字符串合理一些,接下来我们就来做一个实现public static内部的啊,一个静态类。
09:03
我们把这个叫做UV by吧。然后接下来大家记啊,之前的那个window function是一个。接口,而现在的我直接在这儿写啊,Process。Window function,它是一个。它是一个抽象类。啊,因为大家看到它是继承了abstract reach function,它继承了那个负函数,大家记得之前我们讲那个负函数类的时候,就都是抽象类,对吧?哎,所以这个process function啊,Process window function也是一个抽象类啊,所以你写的时候不是implement,是extend。然后它的类型,这里的类型跟window function一样,对吧,也是input output key window,所以用法其实基本上是差不多的,只是比它多了一些东西而已,所以这里边input什么类型呢?当前我们既然是输入的都是event嘛,Input肯定是event了,Output output,我们一句话那就是分析瑞,然后这里来了目前的K姓是什么类型。
10:11
大家会看到当前我们的K是一个布尔类型,对吧?触嘛,所有的数据都放在一起,所以是个bully。然后最后还有一个。Window Windows,看这里的这个定义,泛型的定义,它是w extend window,所以W应该是一个window的子类啊,那么我们这里边可以直接知道啊,先是时间窗口嘛,对吧,Time window嘛,所以innk里边是有这个对应的time window定义的,它是5WINDOW的一个子类,这样的话就可以完整的写出来了。下面报错,那是因为没有实现里边的抽象方法,上边的话你有一个UV count。Window上边就不会报错了,好,接下来我们看一下这里需要去实现的。不是一个process方法,Process方法呢,首先拿到的是啊,首先拿到的是K,跟我们之前那个呃,Window function一样,对吧,拿到一个K,然后呢,Window方式拿到的就是window,这里拿到的是一个contact。
11:13
啊,所以大家就知道了,之前那个是只有窗口的信息,那现在它既然是上下文,那是不是窗口就会多一些啊?呃,那大家看到了,上下文里边有窗口没问题,你可以从这里边拿到它的窗口,也可以获取当前的处理时间,以及当前的water mark,还可以获取跟这个时间相关的信息,另外呢,还可以获取当前的状态啊,你们还还可以去定义状态,获取当前下状态还可以,还有一个output,这是干什么呢?后面我们会讲到,因为它是一个处理函数,处理函数可以有测殊出流去定义。这是它的测殊处理的方法啊,啊,这个我们先先不详细说啊,因为还没有讲到处理函数,大家先大概知道它怎么用就可以了,正就是我们想要的窗口信息,在它里边肯定能拿出来,它还有很多更多的信息。
12:08
然后后边同样输出靠一个collect,一个out来输出,那输入呢,当然这是它不叫这个input了,叫elements一样的嘛,这不就是把所有的输入数据都放到这样一个event类型的集合里边,可迭代集合里边了吗?啊,接下来我们把它都拿出来做一个去重不就完事了吗?哎,那核心应该还是用一个哈奇set对吧?当然你如果要不想用哈set,比方说你用一个这个map,每一个user都对应着一个true false出现过没有的一个值,哎,那你也也是可以的啊,但是最后你还得统计它的个数,所以还是有点麻烦的啊,用一个哈希set。保存user,保存用户的那个名称啊,那这个整体的处理流程其实跟我们之前是一模一样的啊俊said。前我们是把这个存成状态去做增量聚合了,现在我们是要做一个反窗口的,拿到所有数据去做的一个处理。
13:06
又一个哈。然后接下来呢,就是那就是便利喽,对吧,从。Elements风。便利。住句放到set中去。For,这里面就是每一个event。从elements里边取出来,每一个都把它at到user set里边去,是even user at到user set里面去。然后最后还是啊,用这个u s.size当成当前的UV值输出不就完事了吗?哎,那所以当前其实就是我们可以给一个啊当前的这个UV值,那就等于user set.s。啊,那当然了,Size本身得到的只是一个int对吧,得到的是一个int类型,所以假如说啊,我们最后想要输出的是一个浪的话,那你还需要做一个这个强制类型转换啊,或者说重新包装一下,那这里其实没必要,我们这里的这个值也不大啊,你直接把它定义成其准,直接放到串里边输出就完了嘛,啊那这个就无所谓。
14:21
另外,我们还需要结合窗口信息输出是哪个窗口。联合窗口进西。和输出,那这里面窗口有什么信息呢?就是从从几点到几点吗?也就是一个起始点start,一个结束点and从哪里找?上下文context里边。可以直接拿到当前的,我们前面也看到了,它有个属性叫window对吧,那window不可以有个方法叫at that啊,那其实这个window里边我们会看到很多的对应的这个。
15:00
的方法啊,他可以拿到当前的max step啊,当然这是这是window啊,我们现在是这个time window。也可以给大家看一下,这源码里边本身就有这个属性,一个start,一个and,然后get start,那就直接返回这个,对吧?Get and返回这个,那么maxtime Sam它能保存的最大的时间戳是什么呢?是and减一啊,这下大家看到了时间窗口的左臂右开,在源码里边也看到了证据,就是这么去定义的。And,然后同样的方法点window get and,把它拿到最后就可以输出了out.back。你就需要去包装这样一个信息了啊,我们这里是窗口啊窗口,呃,哪个窗口呢。这里就要加上。New,一个time sa。里边的这个值是start。这是它的起始点,然后我们包装成年月日十分秒的是然后诶。
16:04
几点到几点,我们掐一个这个波浪号对吧,然后后面是你有一个step and是我们的窗口什么和什么,然后接下来。我可以换一行啊。然后再加上。他的。UV值。喂。那这个当然就是这里的UV了,直接把当前的这个包装成一个字符串输出就可以了。就是我们整个这个使用的过程啊,这个使用的过程当中,其实是把这个数据先保存到了窗口里边,其实这个本质上它也是把它当成状态了,先存起来,然后再一个一个拿出来去统计一下,放到这个set里边去,去重,然后得到它的结果,看起来好像效率是比较低,但是它好处在于能拿到更多的信息,我们想怎么做怎么做,反正数据都在这了,信息也都在这儿了,你可以任意包装,任意取舍。
17:08
所以接下来我们可以运行一下,看看它得到的效果怎么样。啊,我们需要稍微的等一会儿,因为当前我们并不知道这个数据什么时候大家看现在来了,对吧?啊,现在是这个就看的很明显了啊,就是11:35分到35分零零秒到11:35:10 UV值是二啊,那就有两个用户点了,哎,这个如果如果啊,我们前面加上对应的。数据的话,数据做一个显显示的话,可能会看的更加的清晰,这个是input或者叫data。重新运行一下。啊,大家可以看到这里来了。多条数据是吧,来了六条数据。四个用户都包含了,所以UV值为四,对不对啊,就是窗口三十三十五分,40秒到50秒,很明显,50秒到36分啊,PV值UV值为四,其实后面大家知道,因为十条数据嘛,我们一共就四个用户啊,随机生成后面应该大部分情况UV都是四,然后你可以根据产生的数据判断出来计算的到底对不对啊,这个是能看出来的啊,看的很明显。
18:26
这就是关于全窗口函数啊,Process window function的用法。
我来说两句