

流量统计
1363157985066 13726230503 00-FD-07-A4-72-B8:CMCC 120.196.100.82 i02.c.aliimg.com 24 27 2481 24681 200
1363157995052 13826544101 5C-0E-8B-C7-F1-E0:CMCC 120.197.40.4 4 0 264 0 200
1、对流量日志中的用户统计总上、下行、总流量
主要考虑的是map和reduce。
map端的输入是不用考虑的,都是以文本的形式输入行。map考虑的是输出,数据以什么样去处理比较好。
reduce端的输入是迭代器,要知道输入的迭代器是什么,数据还是要考虑的,以什么样的规则将数据传递给reduce,这是reduce调用的规则,要考虑框架的规则。输出的key是什么,输出的value是什么
因为一个手机号表示一个用户,所以key就是手机号。先考虑Reduce的输入,在考虑map的输出,总上、下行、总流量则为value,包含那么多字符串,可以封装为一个对象。整成了自定义类
mapreduce
map
输入
-------------------------------------------------------
输出:
key:phonenum
value:flowBean(上、下行、总流量) 作为一个整体
数据:(用什么样的数据进行处理)
=======================================================
reduce
输入:
key:phonenum
value:flowBean(上、下行、总流量)作为一个整体
-------------------------------------------------------
输出:
key:phonenum
value:flowBean(上、下行、总流量)作为一个整体
up:down:total
在这里是不需要排序的,因为排序是基于key的,而这里的key只有一个
1、定义一个自定义类,然后类里面包含所需要的属性
2、map端输出,Reduce要拉取数据,所以数据都是需要可序列化的,所以要实现可序列化接口。并且实现它的方法

要有两个构造方法,一个是无参构造,一个是有参构造。有参构造返回的是两个相加

对属性添加get,set的方法

实现序列化的方法(序列化和反序列化的顺序要一致)

实现tostring方法

到此,JavaBean就OK了。
接下来就要写MapReduce(map端一次只处理一行数据)
定义一个类flowCount,而且要继承Mapper,Reduce
1、先将value转为字符串,2、通过空格tab进行切割,3、获取数值,4、调用参数方法计算,5、获取到的k,v放到上下文

实现Reduce方法
1、同一个手机号的values循环,2将值进行统计累加,3、传给参数方法,4、返回的信息给到上下文

驱动方法



13480253104 180 180 360
13502468823 7335 110349 117684
13560436666 1116 954 2070
13560439658 2034 5892 7926
13602846565 1938 2910 4848
最终是要排倒叙的,reduce端的输入是要什么数据,才能得出reduce端所要输出的内容
统计流量且按照流量大小倒序排序(总量倒序、下行、上行倒序,phoneNum正序) 要统计还要倒叙
其实上面第一个Reduce输出的时候,已经是统计完了,现在这个Reduce要对他们进行排序,而排序只是对key进行排序
所以,Reduce的输入就是类,flowBean,则也就是将第一个Reduce的输出的k,v调换为第二个map的输出。
mapreduce
map
输入
key:phonenum
value:13480253104 180 180 360 flowBean
----------------------------------------------------
输出:
key:flowBean
value:phonenum
数据:

=====================================================
reduce
输入:
key:flowBean
value:phonenum
这个是Reduce调用后的,传给Reduce方法(倒叙排序)

------------------------------------------------------
输出:
key:phonenum
value:flowBean(上、下行、总流量)
up:down:total
结果如图

具体代码分析如下
要做比较,所以继承比较的接口,比较flowBean这个类

返回比较的顺序(内部用的是分区加排序)自定义比较

到此flowBean改完了


到此map端改完了

驱动方法的输入输出修改一下

自定义分区
3、统计流量且按照手机号的归属地,将结果数据输出到不同的省份文件中
134 江西0
135 北京1
136 上海2
137 天津3
138 重庆4
139 深圳5
其他 其他
map阶段
输出:
key:
value:
===========================
reducetask:7 7个分区,设置7个reducetask
===========================
reduce阶段
输入:
key:
value:
----------------------------
输出:
key:phonenum (按照号码段输出)
value:flowBean
要自定义Patition类分区,要实现partitioner方法,按照省份进行分区
patitioner是在map端的输出之后,进行分区,patitioner要获取到k值,则需要对key进行分区
数据类型要和map端的输出一样


进行分区

在flowCount类里面修改,将自定义的分区加入。已经设置Reduce的接收的参数

在客户端指定分区数

修改下面的hash取模的分区数
这个是源码的写法

这个是自定义的写法

分组Top1的实现

![]()

top-1的value可以不要,top-n的value是要的
map端输出的是类,shuffle的过程就是要进行分区,还有金额倒序,
Reduce端要将shuffle后端 合并成一个文件,合并过程中也是要排序的,用comparTo排序(比较大小而已)
循环迭代,就是比较key是否相等,而用groupingcomparator欺骗迭代器,也就是实现了同一个订单号调用一次Reduce方法

TOP 1
<Order_0000001,Pdt_01,222.8>
<Order_0000001,Pdt_05,25.8 >
<Order_0000002,Pdt_05,325.8>
<Order_0000002,Pdt_03,522.8>
<Order_0000002,Pdt_04,122.4>
<Order_0000003,Pdt_01,222.8>

先写一个类OrderBean,而且需要实现比较的接口,而且需要序列化







到此Javabean实现了。比普通类多实现序列化方法,和比较方法。
自定义partitioner,将订单号相同的orderBean发到一个Reduce,按订单号进行分区,订单号相同作为一个分区

按照订单号进行分组,功能就是用于欺骗迭代器,
![]()
先要实现一个无参构造,而且实现一个比较方法

最后要实现TopN


写一个驱动方法



在Reduce输出之前呢,将自定义分区,和分组比较的功能加上


top3是三次输出,但是这个是固定写死的

初始化和清空资源,通过context去获取资源,默认设置一个3的参数


方法一:topn的设置,可以动态设置top个数,可以作为参数进行传参
方法二:如果将上面这个注掉,将xml文件引入进来


context是全局性的,每一个参数都可以拿得到

初始化清空资源
setup
reduce
reduce
reduce
.....
cleanup




本文探讨了使用MapReduce处理流量日志数据的方法,详细介绍了如何统计用户流量、实现自定义类、排序与分区策略,以及如何通过MapReduce实现流量统计的高级功能。

674

被折叠的 条评论
为什么被折叠?



