mapreduce实现全局排序
直接附代码,说明都在源码里了。
package com.hadoop.totalsort;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapred.InputSplit;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.LineRecordReader;
import org.apache.hadoop.mapred.RecordReader;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.util.IndexedSortable;
import org.apache.hadoop.util.QuickSort;
public class SamplerInputFormat extends FileInputFormat<Text, Text> {
static final String PARTITION_FILENAME = "_partition.lst";
static final String SAMPLE_SIZE = "terasort.partitions.sample";
private static JobConf lastConf = null;
private static InputSplit[] lastResult = null;
static class TextSampler implements IndexedSortable {
public ArrayList<Text> records = new ArrayList<Text>();
public int compare(int arg0, int arg1) {
Text right = records.get(arg0);
Text left = records.get(arg1);
return right.compareTo(left);
}
public void swap(int arg0, int arg1) {
Text right = records.get(arg0);
Text left = records.get(arg1);
records.set(arg0, left);
records.set(arg1, right);
}
public void addKey(Text key) {
records.add(new Text(key));
}
//将采集出来的key数据排序
public Text[] createPartitions(int numPartitions) {
int numRecords = records.size();
if (numPartitions > numRecords) {
throw new IllegalArgumentException("Requested more partitions than input keys (" + numPartitions +
" > " + numRecords + ")");
}
new QuickSort().sort(this, 0, records.size());
float stepSize = numRecords / (float) numPartitions; //采集的时候应该是采了100条记录,从10个分片查找的,此处再取numPartitions-1条
Text[] result = new Text[numPartitions - 1];
for (int i = 1; i < numPartitions; ++i) {
result[i - 1] = records.get(Math.round(stepSize * i));
}
return result;
}
}
public static void writePartitionFile(JobConf conf, Path partFile) throws IOException {
//前段代码从分片中采集数据,通过sampler.addKey存入TextSampler中的records数组
SamplerInputFormat inputFormat = new SamplerInputFormat();
TextSampler sampler = new TextSampler();
Text key = new Text();
Text value = new Text();
int partitions = conf.getNumReduceTasks(); // Reducer任务的个数
long sampleSize = conf.getLong(SAMPLE_SIZE, 100); // 采集数据-键值对的个数
InputSplit[] splits = inputFormat.getSplits(conf, conf.getNumMapTasks());// 获得数据分片
int samples = Math.min(10, splits.length);// 采集分片的个数 ,采集10个分片
long recordsPerSample = sampleSize / samples;// 每个分片采集的键值对个数
int sampleStep = splits.length / samples; // 采集分片的步长 ,总的分片个数/要采集的分片个数
long records = 0;
for (int i = 0; i < samples; i++) { //1...10分片数
RecordReader<Text, Text> reader = inputFormat.getRecordReader(splits[sampleStep * i], conf, null);
while (reader.next(key, value)) {
sampler.addKey(key); //将key值增加到sampler的records数组
records += 1;
if ((i + 1) * recordsPerSample <= records) { //目的是均匀采集各分片的条数,比如采集到第5个分片,那么记录条数应该小于5个分片应该的条数
break;
}
}
}
FileSystem outFs = partFile.getFileSystem(conf);
if (outFs.exists(partFile)) {
outFs.delete(partFile, false);
}
SequenceFile.Writer writer = SequenceFile.createWriter(outFs, conf, partFile, Text.class, NullWritable.class);
NullWritable nullValue = NullWritable.get();
for (Text split : sampler.createPartitions(partitions)) { //调用createPartitions方法,排序采集出来的数据,并取partitions条
writer.append(split, nullValue);
}
writer.close();
}
static class TeraRecordReader implements RecordReader<Text, Text> {
private LineRecordReader in;
private LongWritable junk = new LongWritable();
private Text line = new Text();
private static int KEY_LENGTH = 10;
public TeraRecordReader(Configuration job, FileSplit split) throws IOException {
in = new LineRecordReader(job, split);
}
public void close() throws IOException {
in.close();
}
public Text createKey() {
// TODO Auto-generated method stub
return new Text();
}
public Text createValue() {
return new Text();
}
public long getPos() throws IOException {
// TODO Auto-generated method stub
return in.getPos();
}
public float getProgress() throws IOException {
// TODO Auto-generated method stub
return in.getProgress();
}
public boolean next(Text arg0, Text arg1) throws IOException {
if (in.next(junk, line)) { //调用父类方法,将value值赋给key
// if (line.getLength() < KEY_LENGTH) {
arg0.set(line);
arg1.clear();
// } else {
// byte[] bytes = line.getBytes(); // 默认知道读取要比较值的前10个字节 作为key
// // 后面的字节作为value;
// arg0.set(bytes, 0, KEY_LENGTH);
// arg1.set(bytes, KEY_LENGTH, line.getLength() - KEY_LENGTH);
// }
return true;
} else {
return false;
}
}
}
@Override
public InputSplit[] getSplits(JobConf conf, int splits) throws IOException {
if (conf == lastConf) {
return lastResult;
}
lastConf = conf;
lastResult = super.getSplits(lastConf, splits);
return lastResult;
}
public org.apache.hadoop.mapred.RecordReader<Text, Text> getRecordReader(InputSplit arg0, JobConf arg1,
Reporter arg2) throws IOException {
return new TeraRecordReader(arg1, (FileSplit) arg0);
}
}
转载自:http://www.open-open.com/lib/view/open1381329062408.html
mapreduce实现全局排序的更多相关文章
- MapReduce TotalOrderPartitioner 全局排序
我们知道Mapreduce框架在feed数据给reducer之前会对map output key排序,这种排序机制保证了每一个reducer局部有序,hadoop 默认的partitioner是Has ...
- 三种方法实现Hadoop(MapReduce)全局排序(1)
我们可能会有些需求要求MapReduce的输出全局有序,这里说的有序是指Key全局有序.但是我们知道,MapReduce默认只是保证同一个分区内的Key是有序的,但是不保证全局有序.基于此,本文提供三 ...
- Mapreduce的排序(全局排序、分区加排序、Combiner优化)
一.MR排序的分类 1.部分排序:MR会根据自己输出记录的KV对数据进行排序,保证输出到每一个文件内存都是经过排序的: 2.全局排序: 3.辅助排序:再第一次排序后经过分区再排序一次: 4.二次排序: ...
- 大数据mapreduce全局排序top-N之python实现
a.txt.b.txt文件如下: a.txt hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop ...
- MapReduce怎么优雅地实现全局排序
思考 想到全局排序,是否第一想到的是,从map端收集数据,shuffle到reduce来,设置一个reduce,再对reduce中的数据排序,显然这样和单机器并没有什么区别,要知道mapreduce框 ...
- Hadoop对文本文件的快速全局排序
一.背景 Hadoop中实现了用于全局排序的InputSampler类和TotalOrderPartitioner类,调用示例是org.apache.hadoop.examples.Sort. 但是当 ...
- 一起学Hadoop——TotalOrderPartitioner类实现全局排序
Hadoop排序,从大的范围来说有两种排序,一种是按照key排序,一种是按照value排序.如果按照value排序,只需在map函数中将key和value对调,然后在reduce函数中在对调回去.从小 ...
- MapReduce分区和排序
一.排序 排序: 需求:根据用户每月使用的流量按照使用的流量多少排序 接口-->WritableCompareable 排序操作在hadoop中属于默认的行为.默认按照字典殊勋排序. 排序的分类 ...
- Hadoop学习笔记—11.MapReduce中的排序和分组
一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...
随机推荐
- eclipse4.2.1插件安装(二)之Eclipse HTML Editor
编辑一些页面文件,例如JSP,HTML,JS等,直接用内置的文本编辑器基本比较疯狂,自己选了一个顺手的编辑器,Eclipse HTML Editor! Eclipse HTML编辑器插件主要提供以下功 ...
- Java实战之04JavaWeb-05事务和连接池
一.事务部分 1.事务的简介 做一件事情,这个一件事情中有多个组成单元,这个多个组成单元要不同时成功,要不同时失败.A账户转给B账户钱,将A账户转出钱的操作与B账户转入钱的操作绑定到一个事务中,要不这 ...
- [转]怎样在cmd(命令提示符)下进行复制粘贴操作
原文链接:http://jingyan.baidu.com/article/93f9803fd3a4dde0e46f55f5.html cmd下复制粘贴的快捷操作方式 工具/原料 系统cmd 步骤/方 ...
- 九度OJ 1410 垒积木 -- 动态规划
题目地址:http://ac.jobdu.com/problem.php?pid=1410 题目描述: 给你一些长方体的积木,问按以下规则能最多垒几个积木. 1 一个积木上面最多只能垒另一个积木. 2 ...
- asp.net导出excel较为简约的代码
ds为数据源 Response.Buffer = true; Response.AppendHeader("Content-Disposition", "attachme ...
- 软件测试之 LoadRunner安装\破解\汉化
一.下载 LoadRunner下载地址:http://kuai.xunlei.com/d/QRNIUASALOIE 二. 安装 1.启动安装程序 运行setup.exe,点击“LoadRunner完整 ...
- Chocolatey:Windows软件包管理器
Chocolatey 2016-08-03 https://chocolatey.org/ Chocolatey是一个Windows软件包管理器,就像Nuget或者npm,或者说类似Linux上的ap ...
- 转载:mysql 对于百万 千万级数据的分表实现方法
一般来说,当我们的数据库的数据超过了100w记录的时候就应该考虑分表或者分区了,这次我来详细说说分表的一些方法.目前我所知道的方法都是MYISAM的,INNODB如何做分表并且保留事务和外键,我还不是 ...
- 51nod贪心算法入门-----活动安排问题2
题目大意就是给几个活动,问要几个教室能够弄完. 这个题目的想法就是把活动的开始——结束的时间看做是数轴上的一段线段,教室的个数就是在某点的时间厚度,求最大的时间厚度就是所需要的教室个数. #inclu ...
- JavaScript事件总结
JavaScript 事件总结 本文总结自<JavaScript高级程序设计>以及自己平时的经验,针对较新浏览器以及 DOM3 级事件标准(2016年8月),对少部分内容作了更正,增加 ...