一、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优化)的更多相关文章

  1. MapReduce分区和排序

    一.排序 排序: 需求:根据用户每月使用的流量按照使用的流量多少排序 接口-->WritableCompareable 排序操作在hadoop中属于默认的行为.默认按照字典殊勋排序. 排序的分类 ...

  2. Hadoop【MR的分区、排序、分组】

    [toc] 一.分区 问题:按照条件将结果输出到不同文件中 自定义分区步骤 1.自定义继承Partitioner类,重写getPartition()方法 2.在job驱动Driver中设置自定义的Pa ...

  3. 分页查询最好加排序(order by)

    昨天,与外部化系统对接时,发现有一个数据一直咩有集成到,双方各自排查了自己系统的代码,都觉得逻辑非常简单,无法就是一个分页查询而已. 问题就出在这个分页查询上. 为了说明当时问题发生的情景,我模拟了一 ...

  4. DataTable列查询加排序

    DataTable列查询加排序 DataRow[] drArray = dt.Select("ANLYCOM_ID='" + chSPrdtStblAnly.AnlyComId + ...

  5. 【译】高级T-SQL进阶系列 (七)【上篇】:使用排序函数对数据进行排序

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 什么是排序函数(Ranking Functions)? 排序函数基于一组记录的集合返回一个排序值.一个排序值其实 ...

  6. Java冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序

    冒泡排序   冒泡排序是一种简单的排序算法.它重复地走访过要排序地数列,一次比较两个元素,如果它们地顺序错误就把它们交换过来.走访数列地工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. ...

  7. 备战秋招之十大排序——O(n^2)级排序算法

    一.冒泡排序 冒泡排序是入门级的算法,但也有一些有趣的玩法.通常来说,冒泡排序有三种写法: 一边比较一边向后两两交换,将最大值 / 最小值冒泡到最后一位: 经过优化的写法:使用一个变量记录当前轮次的比 ...

  8. 【排序算法】——冒泡排序、选择排序、插入排序、Shell排序等排序原理及Java实现

    排序 1.定义: 所谓排序,即是整理文件中的内容,使其按照关键字递增或递减的顺序进行排列. 输入:n个记录,n1,n2--,其对应1的关键字为k1,k2-- 输出:n(i1),n(i2)--,使得k( ...

  9. Jtable 表格按多列排序(支持中文汉字排序)

    这两天公司让做一个Jtable表格的排序,首先按A列排序,在A列相等时按B列排序,B列相等时按C列排序,ABC三列可以任意指定,最多分三列,这样的一个需求.由于我是大神,所以必须做了出来.ok,不自恋 ...

随机推荐

  1. BZOJ 3669 魔法森林

    LCT维护生成树 先按照a的权值把边排序,离线维护b的最小生成树. 将a排序后,依次动态加边,我们只需要关注b的值.要保证1-n花费最少,两点间的b值肯定是越小越好,所以我们可以考虑以b为关键字维护最 ...

  2. Python中的string和bytes的转换

    总的来说,bytes和string的关系是: \(bytes\xrightarrow{decode}string\) \(bytes\xleftarrow{encode}string\) 常见的几种编 ...

  3. [CTSC2018]暴力写挂

    题目描述 www.lydsy.com/JudgeOnline/upload/201805/day1(1).pdf 题解 首先来看这个我们要最大化的东西. deep[u]+deep[v]-deep[lc ...

  4. Mac spotlight无法搜索的解决方法

    出现问题: 1. 在打开spotlight快速搜索的时候输入两个字符,后该搜索框自动会消失,很是奇怪重启等操作也没有效果 问题原因: 可能因为之前因为耗电原因关闭的全局搜索的索引,或者由于索引出现错误 ...

  5. shell 基础(一)

    废话少说 往下看 1. 查看 Shell Shell 是一个程序,一般都是放在/bin或者/user/bin目录下,当前 Linux 系统可用的 Shell 都记录在/etc/shells文件中./e ...

  6. windows下用pycharm安装tensorflow简易教程

    https://blog.csdn.net/heros_never_die/article/details/79760616 最近开始学习深度学习的相关知识,准备实战一下,看了一些关于tensorfl ...

  7. python实现加密

    1.md5加密 hashlib 库中包括如SHA1.SHA224.SHA256.SHA384.SHA512和MD5算法等 >>> import hashlib>>> ...

  8. Servlet 学习

    3.1 概念 运行在服务器端的小程序 Servlet 就是一个接口 定义JAVA类被浏览器访问(Tomact 识别)的规则 将来 我们需要自定义一个类 实现servlet 接口 重写方法 3.2 快速 ...

  9. 金融量化分析【day112】:量化平台的使用-第一个策略

    一.策略代码 # 导入函数库 import jqdata #初始化函数,设定基准等等 def initialize(context): set_benchmark('000300.XSHG') g.s ...

  10. <锋利的jQuery>读书笔记