按数值排序
示例:按气温字段对天气数据集排序
问题:不能将气温视为Text对象并以字典顺序排序
正统做法:用顺序文件存储数据,其IntWritable键代表气温,其Text值就是数据行
常用简单做法:首先,增加偏移量以消除所有负数;其次,在数字面前加0,使所有数字的长度相等;最后,用字典法排序。
streaming的做法:-D mapred.text.key.comparator.options="-k1n -k2nr" 第一个year字段按数值顺序排序,第二个temp字段按数值顺序方向排序

Partitioner 

Mapreduce默认的partitioner是HashPartitioner。除了这个mapreduce还提供了3种partitioner。如下图所示: 

patition类结构

1. Partitioner是partitioner的基类,如果需要定制partitioner也需要继承该类。

2. HashPartitioner是mapreduce的默认partitioner。计算方法是

which reducer=(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks,得到当前的目的reducer。

3. BinaryPatitioner继承于Partitioner< BinaryComparable ,V>,是Partitioner的偏特化子类。该类提供leftOffset和rightOffset,在计算which reducer时仅对键值K的[rightOffset,leftOffset]这个区间取hash。

Which reducer=(hash & Integer.MAX_VALUE) % numReduceTasks

4. KeyFieldBasedPartitioner也是基于hash的个partitioner。和BinaryPatitioner不同,它提供了多个区间用于计算hash。当区间数为0时KeyFieldBasedPartitioner退化成HashPartitioner。

$HADOOP_HOME/bin/hadoop streaming \

-D stream.map.output.field.separator=. \

-D stream.num.map.output.key.fields=4 \

-D map.output.key.field.separator=. \    #map输出分隔符设为“.”

-D num.key.fields.for.partition=2 \    #将key分隔出来的前两个部分而不是整个key用于Partitioner做partition

-input /user/test/input -output /user/test/output \

-mapper “mymapper.sh” -reducer “ myreducer.sh” \

        -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \    #使用KeyFieldBasedPartitioner

-file /home/work/mymapper.sh \

-file /home/work/myreducer.sh \

-jobconf mapred.job.name=”key-partition-demo”

5. TotalOrderPartitioner这个类可以实现输出的全排序。不同于以上3个partitioner,这个类并不是基于hash的。在下一节里详细的介绍totalorderpartitioner。

 
全排序
最简单的方法:所有数据丢给一个reduce,使其内部排序。
这样的方法跟单机没什么区别,完全没有利用分布式计算的优势;数据量稍大时,一个reduce的处理效率极低。
分布式方案:
首先,创建一系列排序好的文件;其次,串联这些文件;最后生成一个全局排序的文件。
主要思路是使用一个partitioner来描述全局排序的输出。
由此我们可以归纳出这样一个用hadoop对大量数据排序的步骤:
1)  对待排序数据进行抽样;
2)  对抽样数据进行排序,产生标尺;
3)  Map对输入的每条数据计算其处于哪两个标尺之间;将数据发给对应区间ID的reduce
4)  Reduce将获得数据直接输出。
这里使用对一组url进行排序来作为例子:
Java实现:
1)InputSampler
输入采样类,可以对输入目录下的数据进行采样。InputSampler类实现了Sampler接口,目的是创建一个顺序文件来存储定义分区的键。提供了3种采样方法。

采样类结构图

采样方式对比表:

类名称

采样方式

构造方法

效率

特点

SplitSampler<K,V>

对前n个记录进行采样

采样总数,划分数

最高

RandomSampler<K,V>

遍历所有数据,随机采样

采样频率,采样总数,划分数

最低

IntervalSampler<K,V>

固定间隔采样

采样频率,划分数

对有序的数据十分适用

InputSampler.Sampler<IntWritable, Text> sampler = new InputSampler.RandomSampler<IntWritable, Text>(
                0.1, 10000, 10);
RandomSampler的三个参数分别是采样率、最大样本数、最大分区。
2)TotalOrderPartitioner 
TotalOrderPartitioner.setPartitionFile(conf, partitionFile);
InputSampler.writePartitionFile(conf, sampler);
InputSampler写的分区文件放在输入目录。
TotalOrderPartitioner指定partition文件。partition文件要求Key (这些key就是所谓的划分)的数量和当前reducer的数量相同并且是从小到大排列。
writePartitionFile这个方法根据采样类提供的样本,首先进行排序,然后选定(随机的方法)和reducer数目-1的样本写入到partition file。这样经过采样的数据生成的划分,在每个划分区间里的key value pair 就近似相同了,这样就能完成均衡负载的作用。 
DistributedCache.addCacheFile(partitionUri, conf);
partition文件载入分布式缓存。

Hadoop的partitioner、全排序的更多相关文章

  1. Hadoop学习笔记: 全排序

    在Hadoop中实现全排序有如下三种方法: 1. 只使用一个reducer 2. 自定义partitioner 3. 使用TotalOrderPartitioner 其中第一种方法显然违背了mapre ...

  2. [大数据相关] Hive中的全排序:order by,sort by, distribute by

    写mapreduce程序时,如果reduce个数>1,想要实现全排序需要控制好map的输出,详见Hadoop简单实现全排序. 现在学了hive,写sql大家都很熟悉,如果一个order by解决 ...

  3. hadoop排序 -- 全排序

    目录 一.关于Reducer全排序 1.1. 什么叫全排序 1.2. 分区的标准是什么 二.全排序的三种方式 2.1. 一个Reducer 2.2. 自定义分区函数 2.3. 采样 一.关于Reduc ...

  4. MapReduce --全排序

    MapReduce全排序的方法1: 每个map任务对自己的输入数据进行排序,但是无法做到全局排序,需要将数据传递到reduce,然后通过reduce进行一次总的排序,但是这样做的要求是只能有一个red ...

  5. Hadoop中的各种排序

    本篇博客是金子在学习hadoop过程中的笔记的整理,不论看别人写的怎么好,还是自己边学边做笔记最好了. 1:shuffle阶段的排序(部分排序) shuffle阶段的排序可以理解成两部分,一个是对sp ...

  6. Hadoop基础-MapReduce的排序

    Hadoop基础-MapReduce的排序 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MapReduce的排序分类 1>.部分排序 部分排序是对单个分区进行排序,举个 ...

  7. Hadoop MapReduce 二次排序原理及其应用

    关于二次排序主要涉及到这么几个东西: 在0.20.0 以前使用的是 setPartitionerClass setOutputkeyComparatorClass setOutputValueGrou ...

  8. 如何使用Hadoop的Partitioner

    如何使用Hadoop的Partitioner 博客分类: Hadoop hadooppartition Hadoop里面的MapReduce编程模型,非常灵活,大部分环节我们都可以重写它的API,来灵 ...

  9. hive中的全排序

    写mapreduce程序时,如果reduce个数>1,想要实现全排序需要控制好map的输出 现在学了Hive,写sql大家都很熟悉,如果一个order by解决了全排序还用那么麻烦写mapred ...

随机推荐

  1. 0环境设置 - SQLPLUS设置

    define _editor=vi - SQL*PLUS默认编辑器set serveroutput on size 1000000 - 默认打开DBMS_OUTPUT, 不用每次使用都执行这个命令来启 ...

  2. [三分]HDOJ 5531 Rebuild

    题意:给n个点,以这n个点为圆心画圆,使得所有的圆与其相邻的圆相切. 求n个圆最小的面积和. 分析:很容易想到确定了其中一个圆的半径之后,其他的圆的半径也能随之确定了. 画一画三个点的和四个点的,会发 ...

  3. U盘安装Win7 64位

    试了好几遍,失败了的就不说了,直接记下成功的方案,方便下次. 方法为:用UltraISO刻镜像文件到U盘,然后U盘启动安装. 具体如下: 刻u盘之前一定要验证iso镜像的完整性啊(可以用文件校验工具与 ...

  4. java.util.concurrent包API学习笔记

    newFixedThreadPool 创建一个固定大小的线程池. shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭. awaitTermination():用于等待子线程结束, ...

  5. spring autoWire注解

    1.autowire注解,可以用来获得applicationContext,ResourceLoader,BeanFactory的注入 autoWire会获得相应资源 2.autoWire注解还可以用 ...

  6. Sina App Engine(SAE)入门教程(4)- SaeVCode(验证码服务)使用

    参考资料 SaeVCode api 文档 使用教程 所有的验证码原理都是生成一个vcode字符串,存到session中,和用户的输入进行比较判断,以下是一个使用验证码服务的完整实例: 首页index. ...

  7. Linux和Linux之间共享目录

    1.Linux 服务器端NFS服务器的配置 以root身份登陆Linux服务器,编辑/etc目录下的共享目录配置文件exports,指定共享目录及权限等. 执行如下命令编辑文件/etc/exports ...

  8. Servlet获取当前服务器的实际路径

    Servlet/Jsp需要操作服务器所拥有的资源,为此需要得到其绝对路径或实际路径, 在Servlet的doGet方法中加入以下代码可以查看服务器的实际路径. package com.mhb; imp ...

  9. C++异常以及异常与析构函数

    1. 抛出异常 1.1 抛出异常(也称为抛弃异常)即检测是否产生异常,在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常. 该语句的格式为: throw 表达式; 如果在try语句 ...

  10. OpenCV在Android平台上的应用

    今年8月份, OpenCV 2.3.1发布了. 虽然从2.2开始, OpenCV就号称支持Android平台, 但真正能让OpenCV在Android上运行起来还是在2.3.1版本上. 在这个版本上, ...