D10 MapRedecu程序案例思路汇总

来源:互联网 发布:软件测试工作怎么样 编辑:程序博客网 时间:2024/06/13 02:27


需求“对日志数据中的上下行流量信息汇总,并输出按照总流量倒序排序的结果:


1363157985066  1372623050300-FD-07-A4-72-B8:CMCC  120.196.100.82   2427248124681 200


1363157995052   138265441015C-0E-8B-C7-F1-E0:CMCC  120.197.40.4        4   0  264      0      200


1363157991076   1392643565620-10-7A-28-CC-0A:CMCC  120.196.100.99   2   4   132    1512  200


1363154400022   139262511065C-0E-8B-8B-B1-50:CMCC  120.197.40.4        4  0   240      0     200

一、
核心对象:上行流量;下行流量;总流量;手机号码;这总共四项。
解决思路:将三个流量参数封装对象,然后将Bean对象作为key来利用map输出的自动排序功能;对于对象来说,想要可写,并且可以按照大小排序必须实现WritableComparable。
①//自定义倒序比较的规则。用总流量的大小作为规则。

return sumflow > o.getSumflow() ? -1:1;

②map输出<Bean,phoneNum>;reduce输出颠倒<phoneNum,Bean>.


二、需求:根据归属地,将流量统计结果输出到不同文件,以便于在查询统计结果时可以定位到省级范围进行
对象对象:同上。
解决思路:无排序;map输出的kv对,会按照相同key分组,然后分发给不同的reducetask。
默认的分发规则为:根据keyhashcode%reducetask数来分发。所以在reduce输出之前要按照我们自己的需求进行分组,将手机号码作为key值,并且也作为分类的依据。就是改写数据分发(分组)组件Partitioner。
key值:132开头的交给reduceTask_1;
            133开头的交给reduceTask_2;
            134开头的交给reduceTask_3;……
具体实现:
①自定义一个类继承抽象类:Partitioner。重写int getPartition()方法通过判断前3位数来返回0-5的某个reduceTask的标识数(这个"132"要和0-5组成HashMap来完成映射)
②在job对象中,设置自定义partitioner: job.setPartitionerClass(CustomPartitioner.class)即可。


三、订单join实例:具体实现是将两张表合并(逻辑复杂)
……………………………………………………………………………………………………………………………………………………………………………………
A方案
实例思路:
a.对于两张表来说,最终输出对象,这个对象应该包括订单里的所有数据。那么对应的表中的信息对应着成员变量;所以按照此封装对象。
b.然后编写map函数,发现是两个文件,那么两个文件对于最终输出结果的特点是“前有后无,前无后有”。那么在读取切片文件时,要根据读取的文件名来分别封装对象的格式:是“前有后无”,还是“前无后有”?这里用到了获得读取切片文件名的API;最终生成了多个成员变量残缺对象
c.最后在reduce中将两个文件产生的多个对象来拼接,拼接的key就是产品id(两张表里都有的),将产品的信息追加到订单的后面。
d.这是遇到问题是不能确定生成的如此多对象哪个是订单的,哪个是产品的?解决办法是对两个表生成的对象加上标识,
那么封装对象时要添加一个成员变量flag;并且在map函数中生成对象时追加上。
e.剩下的就是在reduce函数中,通过判断flag来追加产品信息的数据。首先按照pid遍历所有的对象,即得到了一系列关于k值排序的对象,
特点是:一批订单携带一个产品的信息,然后将订单存储列表;然后遍历:将产品信息取出,赋值到每一个订单,并且输出。
mapper的按照k值的排序导致了每个切片数据读取后必携带一个商品的信息,那么在reducer处理的时候,将其成员变量赋值到订单中即可。
******———
******———
******———
******———
******———
******——— 将订单信息存储列表,然后遍历赋值商品信息即可。找到两张表的共同的id,然后排序。确定算法。
******———
******———
******———
******———
******———
******——— //以上是订单信息
———****** //带商品信息
……………………………………………………………………………………………………………………………………………………………………
B方案:
通过阅读父类Mapper的源码,发现 setup方法是在maptask处理数据之前调用一次 可以用来做一些初始化工作
解决方案:
①在map函数前重写setup()方法:
初始化过程---->读入产品信息(string_id , string pdInfo),存储到Map中,并且Driver中设置缓存文件job.addCacheFile(new URI("file:/D:/Input/pdts.txt"));
②然后在map中读取订单信息后,通过订单中的pid来映射到Map(pid,info)中的pdInfo,追加到输出信息中k.set("%&^$*")。
考虑问题:不通过setup方法写,而是简单定义,那么??再议。


四、关键词索引
解决的问题:从一系列文件中,获取各个字段出现在各个文件出现的次数
核心解决策略:将某字段和文件名作为key,然后遍历自加即可,或者统计IntWritable(1)即可


五、qq好友找出:任意两个人都有共同好友。(允许单向好友)
A:1,3,5,7,2,4,8;  左侧是文件中数据的格式。
B:1,3,9,0;
C:1;
第一步的MR:
读取的每行数据变成如下格式。即完成用户和好友的格式。
1,A     1,B    1,C
3,A     3,B
5,A     9,B
7,A     0,B
2,A
4,A
8,A
map输出是排序后的,实际中排序并无影响。按照key排列进入reduce是如下
1,A
1,B
1,C
3,A
3,B
5,A
……
然后reduce逻辑是,对共同好友的用户进行append()方法追加构成字符串;reduce输出:
1:A,B,C;
3:A,B;
5:A;
……
第二步的MR:
分别完成共同好友1,3,5的用户做key;完成任意两个好友的组合成key
A-B:1;
A-C:1;
B-C:1;

A-B:3;
A:5;
……
最后reduce的输出,按照用户对做key读入,然后追加append();共同好友,再输出
A-B:1,3;
A-C:1;
B-C:1;
A:5;
……

原创粉丝点击