参考:
hadoop二次排序
1. 案例详情描述
1.1 输入数据
共7个 csv 文件,每个文件格式相同,每个文件记录某视频网站一天的日志,以20190106为例截取片段如下:
xx xxx xx xx area_id xx view_type xxx date
7159 ad01 5 0 0000 1.1 2 echwg14702mez165 20190106
7160 ad09 15 2 1200 1.1 2 fhmfy15117dzg176 20190106
7161 ad12 15 3 3900 2.2 2 wffye14422fzf124 20190106
7162 ad04 5 0 8700 2.1 1 xzhax15461hcm186 20190106
7163 ad98 15 6 9000 1.1 1 hyhwz15347ezh175 20190106
7164 ad21 5 0 4200 2.1 2 ffyzh14561ywa129 20190106
7165 ad77 5 0 2600 4.1 1 yfhzd13811aey182 20190106
7166 ad03 15 5 1600 2.1 1 affha13838eha171 20190106
...
其中,一条数据记录一次广告播放行为,与本需求相关字段解释,
- area_id 列:区域编码
- view_type 列:共2种值,分别是1和2,其中1代表曝光行为,2代表点击行为。
- date 列:日期
1.2 需求
根据日期和区域统计每天的曝光量和点击量,每天的结果输出到一个文件。
1.3 输出数据
最终输出7个文件,以其中一个文件为例,截取片段如下:
20190106 0000 40 14
20190106 1200 65 23
20190106 1300 32 16
20190106 2000 80 27
20160106 2700 90 32
...
2. 相关概念及思路分析
2.1 相关概念
- 二次排序:首先按照第一字段排序,然后再对第一字段相同的行按照第二字段排序,注意不能破坏第一次排序的结果。
- 自定义复合键:hadoop 里面的 key 必须是可排序的,自定义复合键能够帮助实现需要二次排序的需求。
- 分区 partitioner : 决定了 map task 输出的每条数据交给哪个 reduce task 处理,默认实现为 hashpartitioner,最终每个 reduce task 生成一个输出结果文件。
- 分组 grouping : 适用于需要根据复合键里面的某一个变量进行二次操作,然后相同该变量的键值对调用一次 reduce 方法。
该需求可以用两种方法实现,一种简单,一种相对繁复但是能够覆盖所有知识点,解释如下:
要求每天的结果输出一个文件,即7个结果文件,倒推对应7个 reduce task -> 相同日期的数据去往相同的 reduce task -> partitioner 需要根据日期来决定每条数据对应的 reduce task。所以 partitioner 在两种方法里是相同的。
2.2 思路一
整体实现思路如下:
- map 方法:先对区域编码排序,具体就是以区域编码为键,日期、曝光量、点击量为值,即 map 输出:
key : areaId, value : date, pv, click - partitioner 分区:需要将同一天的所有数据交给同一个 reduce task处理,因此自定义分区实现而非使用默认的哈希分区,如可使用:
转换日期为对应的整型数据,然后对reduce task数量取余数
这种取余方法同时对日期实现了排序,即最终输出结果目录日期有序。 - reduce 方法:根据原理,reduce方法里接收的参数中,value是一个迭代的值,框架把key 相同的k-v的v值,放在一个迭代器里。在此迭代器里面实现对每个key : areaId 下一组pv, click 的累加统计操作。每次迭代完成,写出一条数据,每个 redu