00:00
啊,我们更常见的要做的流量统计指标,其实是PVUV这样的一些指标,对吧,大家想一想前面实现的这个热门页面浏览统计,它其实更像一个什么呢。更像一个一个PV page view这样的一个统计,对不对,只不过是在page view的基础上还做了一个。做了一个排序和top n的一个选取,对吧?所以相当于如果我们要是简单的去统计PV的话,那是不是应该就只做前面那一步就可以了啊,所以接下来我们在基于另外的数据,比方说我们要基于买点日志的数据,再去做一个网络流量统计啊,那这一部分就是只要我们有买点数据,这这种实现其实是非常非常简单的。那首先我们先来做一个这个PV的统计吧,PV大家知道是什么指标?它的全称就是page view,其实就是说的网站的页面浏览量对不对啊,就是看有多少个人,然后多少人次啊,就是点开了这个页面,然后呃,做了一个页面浏览,那一般我们的统计就是用户每点一次,或者说哎,每打开一个页面啊,这种状态是不是就要统计一次PV啊,就把它收进来对不对啊,所以这个数据呢,其实是最容易统计,最简单的,而且呃也是。
01:30
大家最容易接受,最容易理解的一一个指标,但是他可能也会有一些问题,就是说有时候一个用户他有可能这个,呃,网络卡对吧,频繁的去点击,或者说他就是故意要去刷这个点击量,然后拼命的在那里点击,甚至是一个一个代码程序在那里不停的点啊,这种都是有可能的,所以往往实际应用当中,我们要统计PV,还要统计另外一个指标,还要统计UV,对吧?啊,所以这两个我们往往都是放在一起去做这个处理的,那现在我们统计PV的方法给大家可以介绍两种,一种就是前边讲到的,从web日志里边是不是可以直接按照我们这个访问的这个次数,对吧,发起了多少次请求就可以统计出PV,对不对啊,当然这个要做那个筛选啊,你不能说是发起请求的时候,请求一个CSS,请求一个JS,这个都叫PV,这个这个肯定就不对了,肯定是访问页面的。
02:30
个请求才算批委,那另外还可以怎么做呢?我们可以从请求去考虑,也可以从用户的点击行为去考虑,对不对啊,所以如果说我们在不管是前台还是后台做了买点的话,是不是从买点日志里边也可以把对应的行为选取出来做统计啊,那大家会想到在前面那个买点日志user behavior里边有一个。有一种行为有一个字段也可以表示用户对页面的浏览,那就是是不是还是有一个PV行为啊,相当于就是点击对不对啊,我们一开始是把它作为这个用户这个热门商品的一个指标了,那如果把它作为PV的一个指标,其实也是可以的啊,所以接下来我们就还是用user behavior的那个。
03:23
数据源,买点日志作为数据源来实现一下这个PV的统计啊,这个也非常简单啊,一般PV的这个要求呢,他可能不是滑动窗口的这样的一个需求,而是怎么样,我就统计一段时间对吧,我一天的一个小时的就统计一个滚动窗口的数据就可以,呃,那其实实现起来会更加简单对吧?好,所以接下来我们就。在代码里边做一个实现。呃,那同样我们还是在这里边去用一个object对吧?呃,那么这个object我们的名字就叫做PV吧。
04:10
同样,这个内函数。呃,大家想一下,这里边可能是不是还需要有有这个样例类啊,这里我们要样样例类应该是什么呢。其实就还是user behavior对不对?呃,之前我们那个在hot it里边是不是定义过啊,我们现在还把这个copy过来。呃,这些当然是可以提取出来都放在一起啊,这里边我们就是因为不同的拈嘛,把它隔离开,就是各自处理各自的就好了,然后接下来我们看这个代码里边的主流程,主流程的话常规流程一样,对吧?这个大家都已经写的非常熟悉了,先把环境创建出来,然后接下来,哦,时间语义对吧?我们当前的时间语义应该还是用对,还是even time,因为既然是从这个日志买点日志里边拿的嘛,我们关心的还是当时事件发生的时间,另外不影响结果正确啊,我们set并行度是一,然后接下来。
05:21
这个数据文件从哪里去读这个数据呢?那是不是还是这个user behavior这个数据啊,对吧?呃,当然这个我也可以指定,就是从这个hot it下面去读,一般我们还是要把这个放在。当前的resources下面。呃,然后这里边我们引入的时候,大家会看到前面其实引入的这个过程当中,这个路径非常非常长,对吧。这这个好像实现起来有一点,而且这个是前面的路径是hard code的,这个好明显,我们提交的时候,如果你要是测试环境里边把这个路径写死,然后到时候提交到那个运行环境里边,是不是肯定会有问题啊啊,所以这种方式其实并不好,那更常见的方法是什么呢?对,是不是应该先去获取,就用相对路径对吧?先获取当前的那个resource,所以这里边我们定义一下,用相对路径定义数据源,我可以先定义一个resource,那这个我用get class,它下面有一个方法叫get resource对吧?这里边我们把当前这个文件的相对路径传入。
06:52
好,就use behavior,对不对?然后接下来定义一个data stream read,呃,Read text file,还是这样对吧?那我们现在传的就是什么呢?就是resource.get pass,把它传进去是不是这样就可以了,这样就不会有我们当前这个开发环境里边写死的那些路径了,对不对啊,这种方式其实更常见一点啊。
07:22
然后接下来是不是要做对应的操作啊,Map转换成想要的样例类类型同样还是啊data array先要去做切分,呃,它是按照什么切分的呢?啊,那个还是逗号对不对?CSV文件吧,按照逗号切分,这个是不是跟我们之前这个应该是一模一样啊啊那所以我直接把这个代码也copy过来吧。呃,No,这个有behavior自己有对吧,不用他那里的。
08:03
然后接下来。哎,大家会想到这个分配时间戳和watermark,跟那边也一样,因为它是升序数据,是不是直接分配一个时间戳就完事,这里边用的是time stamp,还要乘以1000,对吧?啊,接下来我们统计这个PV的时候,是不是用的就是PV那个字段啊,啊,所以这里边同样还是做一个filter filter。元素的behavior要等于PV。值统计PV操作。那大家会想到接下来是干什么呀,是不是就是一个PV count一次一个PV count一次直接数出来就完事了呀,大家想想是不是这样,所以这个过程是不是类似于类似于就是一个word count啊啊,所以这个简直再简单不过了啊,前面我们都定义好了之后,这个直接就是一个work,那是不是直接data。
09:16
我们把它包装成一个啊,那那这个都不用data塔了,我是不是直接给一个固定的一个字段,把这个包装成一个二元组,后面跟一个一就完事了,对吧,是不是来一个数据,我就把它转换成一个叫呃PVE1这样的一个东西啊,对吧?然后。是不是做一个K,然后就可以聚合some了?KY根据哪个字段去KI呢?大家看我是直接给了一个固定字段叫PV,这是不是相当于是一个不起什么作用的一个K,对不对啊,有时候把这种叫做ya key啊,就是大mmi k,所以这里边是不是就用这个key去做一个K败,然后开窗去做聚合啊,Time window当前的这个窗口定义的是。
10:15
诶,这个哦,好可以引入啊。一个小时之内的PV,那么OURS1,然后接下来啊,假如我们不包装任何的输出数据类型的话,那是不是直接sum就完事了,对吧?直接sum调这个最简单的聚合函数SUM1是不是就搞定了?就是我们当时的这个这两个二元组元素里边,用第一个元素PV这个字段去做K败,那是不是就是所有的都在一个组里面啊,所有的都统计对不对,如果诶这里为什么把它包装成二元组,然后做这这样的一个KBY操作,这里边我们是想直接ta window开窗,然后直接聚合,如果不做这种操作的话。
11:02
那是不是应该用什么操作直接基于data stream可以直接去统计吗?也可以,那开窗的时候就要用。Window or对吧?呃,那那是不是就可以那个time window or去做那种操作啊,啊其实也是类似啊,就是把它直接全放在一组里面去做操作啊,那这里边这个SUM1,然后print。呃呃,当然这里边我们把这个还是data stream单独打印出来啊,这里面我们可以给一个给一个string,就是打印的输输出什么结果对不对啊,这里边就是当前的这个PV。最后执行。Page view drop对吧,这就是我们这一部分代码啊,大家看这个非常简单对吧,跟那个world com基本上差不多,测试一下吧。
12:05
好,大家可以看到我们运行的结果是不是输出了每一个,呃,一小时输出一次对吧?哎,这里为什么输出这么快呢?因为我们现在相当于是直接把历史数据直接重放一遍,那处理过程其实很快,但实际的那个呃,统计的数据,我们的even time是不是过了一小时啊,对吧?这里边是一小时输出一次的,但是处理时间其实很快就把它回放过去了啊,这里大家也可以看到不同时间语义的这个含义,所以大家可以大概的看一下啊,这每一个时间窗口内的统计的这个PV大概有多少啊。啊,都有四万多对不对,高峰的时期是有52000多啊,最后一个时间窗口比较少,因为我们数据不全嘛,只有13对吧,所以大概是这个四万多五万多这样一个水平,大家可以大概先把这个记住啊。
13:02
记住,它是为了干什么呢?啊,主要是为了接下来大家会发现这里边的统计是不是把同样的对一个人点了多次的这些是不是都算进去,都算做一次PV了,但实际应用场景里边,我们往往是要对这种情况做一个处理的,因为一个人他频繁的去点击,去刷这个点击量,那嗯,你这显然是不合理的嘛,我们其实更更加想要去关注的一个指标是有多少不同的用户,不同的user点击了我们的页面啊,那这个指标其实是我们所说的啊,就是所谓的UV。
我来说两句