一、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. mysql 如何优化left join

    今天遇到一个left join优化的问题,搞了一下午,中间查了不少资料,对MySQL的查询计划还有查询优化有了更进一步的了解,做一个简单的记录: select c.* from hotel_info_ ...

  2. 11.4 Flask session,闪现

    session 加密后放在用户浏览器的 cookie 中 于django 的自带session 不同,flask 的 session 需要导入 from flask import session 添加 ...

  3. Springboot 1.简介 及第一个demo

    按照官网上的新建一个maven项目,然后将类引入pom.xml文件中 <?xml version="1.0" encoding="UTF-8"?> ...

  4. 分布式监控系统开发【day38】:监控trigger表结构设计(一)

    一.需求讨论 1.zabbix触发器的模板截图 1.zabbix2.4.7 2.zabbix3.0 2.模板与触发器关联的好处 好处就是可以批量处理,比如我说我有1000机器都要监控cpu.内存.IO ...

  5. 第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案

    一. 背景 揭秘: 在前面的章节介绍过,Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然也可以基本业务需要的多线程场景,但它们在多个线程的等待处理方面 ...

  6. Web概述

    Web概述 1. JavaWeb 使用java开发的基于互联网的项目 2. 软件架构 C/S:客户端服务器架构 优点:用户体验好,很多数据在本地 缺点:安装.开发.部署.维护麻烦 B/S:浏览器服务器 ...

  7. 数据结构Java实现04---树及其相关操作

    首先什么是树结构? 树是一种描述非线性层次关系的数据结构,树是n个数据结点的集合,这些集结点包含一个根节点,根节点下有着互相不交叉的子集合,这些子集合便是根节点的子树. 树的特点 在一个树结构中,有且 ...

  8. [物理学与PDEs]第3章第5节 一维磁流体力学方程组 5.2 一维磁流体力学方程组的 Lagrange 形式

    由 $$\bex \cfrac{\p \rho}{\p t}&+u_1\cfrac{\p \rho}{\p x}+\rho\cfrac{\p u_1}{\p x}=0, \eex$$ 我们可以 ...

  9. Nginx详解篇

    Nginx主配置文件和参数: Nginx的默认站点目录是Nginx安装目录/application/nginx/下的html目录,如果要部署网站业务,只需要把开发号好的程序全部放置到/applicat ...

  10. L1-Day2

    L1-Day21.明智的人从来不生气. [我的翻译]A wise man is never angry. [标准答案]A wise man never gets angry. [对比分析]be和get ...