Mapreduce的排序(全局排序、分区加排序、Combiner优化)
一、MR排序的分类
1.部分排序:MR会根据自己输出记录的KV对数据进行排序,保证输出到每一个文件内存都是经过排序的;
2.全局排序;
3.辅助排序:再第一次排序后经过分区再排序一次;
4.二次排序:经过一次排序后又根据业务逻辑再次进行排序。
二、MR排序的接口——WritableComparable
该接口继承了Hadoop的Writable接口和Java的Comparable接口,实现该接口要重写write、readFields、compareTo三个方法。
三、流量统计案例的排序与分区
/**
* @author: PrincessHug
* @date: 2019/3/24, 15:36
* @Blog: https://www.cnblogs.com/HelloBigTable/
*/
public class FlowSortBean implements WritableComparable<FlowSortBean> {
private long upFlow;
private long dwFlow;
private long flowSum; public FlowSortBean() {
} public FlowSortBean(long upFlow, long dwFlow) {
this.upFlow = upFlow;
this.dwFlow = dwFlow;
this.flowSum = upFlow + dwFlow;
} public long getUpFlow() {
return upFlow;
} public void setUpFlow(long upFlow) {
this.upFlow = upFlow;
} public long getDwFlow() {
return dwFlow;
} public void setDwFlow(long dwFlow) {
this.dwFlow = dwFlow;
} public long getFlowSum() {
return flowSum;
} public void setFlowSum(long flowSum) {
this.flowSum = flowSum;
} @Override
public void write(DataOutput out) throws IOException {
out.writeLong(upFlow);
out.writeLong(dwFlow);
out.writeLong(flowSum);
} @Override
public void readFields(DataInput in) throws IOException {
upFlow = in.readLong();
dwFlow = in.readLong();
flowSum = in.readLong();
} @Override
public String toString() {
return upFlow + "\t" + dwFlow + "\t" + flowSum;
} @Override
public int compareTo(FlowSortBean o) {
return this.flowSum > o.getFlowSum() ? -1:1;
}
} public class FlowSortMapper extends Mapper<LongWritable, Text,FlowSortBean,Text> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//获取数据
String line = value.toString(); //切分数据
String[] fields = line.split("\t"); //封装数据
long upFlow = Long.parseLong(fields[1]);
long dwFlow = Long.parseLong(fields[2]); //传输数据
context.write(new FlowSortBean(upFlow,dwFlow),new Text(fields[0]));
}
} public class FlowSortReducer extends Reducer<FlowSortBean,Text,Text,FlowSortBean> {
@Override
protected void reduce(FlowSortBean key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
context.write(values.iterator().next(),key);
}
} public class FlowSortPartitioner extends Partitioner<FlowSortBean, Text> {
@Override
public int getPartition(FlowSortBean key, Text value, int i) {
String phoneNum = value.toString().substring(0, 3); int partition = 4;
if ("135".equals(phoneNum)){
return 0;
}else if ("137".equals(phoneNum)){
return 1;
}else if ("138".equals(phoneNum)){
return 2;
}else if ("139".equals(phoneNum)){
return 3;
}
return partition;
}
} public class FlowSortDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//设置配置,初始化Job类
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); //设置执行类
job.setJarByClass(FlowSortDriver.class); //设置Mapper、Reducer类
job.setMapperClass(FlowSortMapper.class);
job.setReducerClass(FlowSortReducer.class); //设置Mapper输出数据类型
job.setMapOutputKeyClass(FlowSortBean.class);
job.setMapOutputValueClass(Text.class); //设置Reducer输出数据类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(FlowSortBean.class); //设置自定义分区
job.setPartitionerClass(FlowSortPartitioner.class);
job.setNumReduceTasks(5); //设置文件输入输出类型
FileInputFormat.setInputPaths(job,new Path("G:\\mapreduce\\flow\\flowsort\\in"));
FileOutputFormat.setOutputPath(job,new Path("G:\\mapreduce\\flow\\flowsort\\partitionout")); //提交任务
if (job.waitForCompletion(true)){
System.out.println("运行完成!");
}else {
System.out.println("运行失败!");
} }
}
注意:再写Mapper类的时候,要注意KV对输出的数据类型,Key的类型一定要为FlowSortBean,因为在Mapper和Reducer之间进行的排序(只是排序)是通过Mapper输出的Key来进行排序的,而分区可以指定是通过Key或者Value。
四、Combiner合并
Combiner是在MR之外的一个组件,可以用来在maptask输出到环形缓冲区溢写之后,分区排序完成时进行局部的汇总,可以减少网络传输量,进而优化MR程序。
Combiner是用在当数据量到达一定规模之后的,小的数据量并不是很明显。
例如WordCount程序,当单词文件的大小到达一定程度,可以使用自定义Combiner进行优化:
public class WordCountCombiner extends Reducer<Text,IntWritable,Text,IntWritable>{
protected void reduce(Text key,Iterable<IntWritable> values,Context context){
//计数
int count = 0; //累加求和
for(IntWritable v:values){
count += v.get();
}
//输出
context.write(key,new IntWritable(count));
}
}
然后再Driver类中设置使用Combiner类
job.setCombinerClass(WordCountCombiner.class);
如果仔细观察,WordCount的自定义Combiner类与Reducer类是完全相同的,因为他们的逻辑是相同的,即在maptask之后的分区内先进行一次累加求和,然后到reducer后再进行总的累加求和,所以在设置Combiner时也可以这样:
job.setCombinerClass(WordCountReducer.class);
注意:Combiner的应用一定要注意不能影响最终业务逻辑的情况下使用,比如在求平均值的时候:
mapper输出两个分区:3,5,7 =>avg=5
2,6 =>avg=4
reducer合并输出: 5,4 =>avg=4.5 但是实际应该为4.6,错误!
所以在使用Combiner时要注意其不会影响最中的结果!!!
Mapreduce的排序(全局排序、分区加排序、Combiner优化)的更多相关文章
- MapReduce分区和排序
一.排序 排序: 需求:根据用户每月使用的流量按照使用的流量多少排序 接口-->WritableCompareable 排序操作在hadoop中属于默认的行为.默认按照字典殊勋排序. 排序的分类 ...
- Hadoop【MR的分区、排序、分组】
[toc] 一.分区 问题:按照条件将结果输出到不同文件中 自定义分区步骤 1.自定义继承Partitioner类,重写getPartition()方法 2.在job驱动Driver中设置自定义的Pa ...
- 分页查询最好加排序(order by)
昨天,与外部化系统对接时,发现有一个数据一直咩有集成到,双方各自排查了自己系统的代码,都觉得逻辑非常简单,无法就是一个分页查询而已. 问题就出在这个分页查询上. 为了说明当时问题发生的情景,我模拟了一 ...
- DataTable列查询加排序
DataTable列查询加排序 DataRow[] drArray = dt.Select("ANLYCOM_ID='" + chSPrdtStblAnly.AnlyComId + ...
- 【译】高级T-SQL进阶系列 (七)【上篇】:使用排序函数对数据进行排序
[译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 什么是排序函数(Ranking Functions)? 排序函数基于一组记录的集合返回一个排序值.一个排序值其实 ...
- Java冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序
冒泡排序 冒泡排序是一种简单的排序算法.它重复地走访过要排序地数列,一次比较两个元素,如果它们地顺序错误就把它们交换过来.走访数列地工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. ...
- 备战秋招之十大排序——O(n^2)级排序算法
一.冒泡排序 冒泡排序是入门级的算法,但也有一些有趣的玩法.通常来说,冒泡排序有三种写法: 一边比较一边向后两两交换,将最大值 / 最小值冒泡到最后一位: 经过优化的写法:使用一个变量记录当前轮次的比 ...
- 【排序算法】——冒泡排序、选择排序、插入排序、Shell排序等排序原理及Java实现
排序 1.定义: 所谓排序,即是整理文件中的内容,使其按照关键字递增或递减的顺序进行排列. 输入:n个记录,n1,n2--,其对应1的关键字为k1,k2-- 输出:n(i1),n(i2)--,使得k( ...
- Jtable 表格按多列排序(支持中文汉字排序)
这两天公司让做一个Jtable表格的排序,首先按A列排序,在A列相等时按B列排序,B列相等时按C列排序,ABC三列可以任意指定,最多分三列,这样的一个需求.由于我是大神,所以必须做了出来.ok,不自恋 ...
随机推荐
- 【XSY2843】「地底蔷薇」 NTT什么的 扩展拉格朗日反演
题目大意 给定集合\(S\),请你求出\(n\)个点的"所有极大点双连通分量的大小都在\(S\)内"的不同简单无向连通图的个数对\(998244353\)取模的结果. \(n\le ...
- Routing 为 Magento 2 一个重要的部分,本文介绍基本应用
Routing 为 Magento 2 一个重要的部分,本文介绍基本应用 Magento 2请求的流程 在Magento 2中,请求URL将如下所示: http://example.com/index ...
- emwin 之模态窗口
@2019-02-27 [小记] emwin 窗口被模态之后,创建子窗口则原模态窗口变为非模态
- busybox编译
sync.c:(.text.sync_main+0x7c): undefined reference to `syncfs'Coreutils—>sync选项去掉 nsenter.c:(.tex ...
- platform驱动分离
目录 platform驱动分离 框架结构 与输入子系统联系 设备描述 驱动算法 注册机制 程序 测试 platform驱动分离 框架结构 与输入子系统联系 设备描述 驱动算法 注册机制 程序 测试 - ...
- Hadoop记录- Yarn scheduler队列采集
#!/bin/sh ip=10.116.100.11 port=8088 export HADOOP_HOME=/app/hadoop/bin rmstate1=$($HADOOP_HOME/yarn ...
- https://www.chromestatus.com/features/5093566007214080
移动端滑动报错:Unable to preventDefault inside passive event listener due to target being treated as passiv ...
- ACM-ICPC 2018 徐州赛区网络预赛 G Trace(思维+set)
https://nanti.jisuanke.com/t/31459 题意 n个矩阵,不存在包含,矩阵左下角都在(0,0),给右上角坐标,后来的矩阵会覆盖前面的矩阵,求矩阵周长. 分析 set按照x或 ...
- 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
一. 开篇说明 EF的性能问题一直以来经常被人所吐槽,究其原因在于“复杂的操作在生成SQL阶段耗时长,且执行效率不高”,但并不是没有办法解决,从EF本身举几个简单的优化例子: ①:如果仅是查询数据,并 ...
- mysql用户管理与备份
用户管理 我们知道在Mysql中root用户是最高权限的用户,其他用户的创建和权限授予都是通过root用户来操作的 查看用户 在root用户界面下 select user,host,password ...