hadoop全局排序思路




import java.net.URI;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.SequenceFile.CompressionType;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.mapred.lib.InputSampler;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.filecache.DistributedCache;
import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
import org.apache.hadoop.mapreduce.lib.partition.TotalOrderPartitioner;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;


import com.lenovo.caojian.quanweizhinan.mapreduce.MissingTemperatureFields_new_version;


/**全排序
 * 如何用hadoop产生一个全局排序的文件?最简单的方法是使用一个分区(a single partition)
 * 但该方法在处理大型文件时效率极低,因为一台机器必须处理所偶的输出文件,从而完全丧失了Mapreduce所提供的并行架构
 * (更好的回答是使用pig 或者hive,他们都可以使用一条指令进行排序)
 * (select * from (select * from table distribute by time sort by time desc limit 50 ) t order by time desc limit 50;);
 * (select * from (select * from table distribute by time sort by time desc limti 50) t order by time  desc limit 50);
 * 事实上任有替代方案:首先,创建一系列排好序的文件,其次串联这些文件,最后生成一个全局排序的文件,主要思想是使用一个一个partitioner来描述输出
 * 的全局排序,例如,可以为上述文件创建四个分区,在第一个分区。。。。。。。。。。。。。
 * 该方法的关键是在于如何划分各个分区,理想情况下,各个分区所含记录数应该大致相等,使作业的总体执行时间不会受制于个别reduce。
 * 在前面提到的分区方案中。各分区的相对大小如下所示。
 * InputSampler类实现了Sampler接口,该接口的唯一成员方法(即getSampler)有两个输入参数(一个InputFormat对象,和一个job对象)
 * 返回一系列样本键
 * public interface Sampler<K,V>{
 *  K[] getSample(InputFormat<K,V> inf, Job job)throws IOExceeption, InterruptedException;
 *  }
 * 
 * 8-8调用TotalOrderPartitioner按IntWritable键对顺序文件进行全局排序
 * 该程序使用RandomSampler以指定的采样率均匀的从一个数据集中选择样本,
 * 在本例中,采样率设置为0.1 ,RamdomSampler的输入参数还包括最大样本数和最大分区(本例中分别是 10000,10这也是InputSampler作为应用程序运行时默认设置
 * 只要任意一个限制条件满足,即停止采样。采样器在客户端运行, 因此限制分片的下载量以加速采样器的运行就尤为重要
 * 在实战中,采样器的运行时间仅占用运行时间的小部分。
 * 为了和集群上面运行的其他任务共享分区文件, InputSampler需要将其缩写的分区文件加入到分布缓存中
 * 以下方案分别以 -5.6C ,13.9C, 22.0C 为边界得到4个分区,易知,新方案比旧方案更加均匀。
 * 输入数据的特性决定如何挑选最合适的采样器,以SplitSampler为例,它只采样了一个分片中的前N条记录,由于并
 * 未从所有分片中广泛采集,该采样器并不适合已经排好序的数据。
 * 另外一方面,IntervalSample以一定的间隔定期从分片中选择键,因此对于已经排好序的数据来说是一个更好的选择
 * RandomSampler是优秀的通用采样器,如果没有可以满足应用需要(记住采样器的目的是创建大小近似相等的一系列分区)
 * ,智能写程序来实现Sampler接口。
 * InputSampler类和TotalOrderPartitioner类的一个好特性是用户可以自由定义分区数,
 * 该值通常取决与集群上reducer槽的数量(该值需要稍小于reducer槽的总数,以应付可能出现的故障)
 * 由于TotalOrderPartitioner只用于分区边界均不相同的时候,因而当键空间小时,设置太大的分区
 * 可能会导致数据冲突。
 * hadoop jar hadoop-examples.jar SortByTemperatureUsingTotalOrderPartitioner
 *  -D mapred.reduce.tasks=30 input/ncdc/all-seq output-totalsort
 *  该程序输出30个内部排好序的分区,切分区中i中的所有键小于分区i+1中的键。
 */
/**
 * Sampler接口有三个子类
 * 1、IntervalSampler 以一定的时间间隔定期从分片中选择键
 * 2、RandomSampler 随机选择
 * 3、SplitSampler 只采样分片中的前n条记录
 */
public class SortByTemperatureUsingTotalOrderPartitioner extends Configured implements Tool {


    @Override
    public int run(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = new Job(conf);
        if (job == null) {
            return -1;
        }
        job.setInputFormatClass(SequenceFileInputFormat.class);
        job.setOutputKeyClass(IntWritable.class);
        job.setOutputFormatClass(SequenceFileOutputFormat.class);
        SequenceFileOutputFormat.setCompressOutput(job, true);
        SequenceFileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
        SequenceFileOutputFormat.setOutputCompressionType(job, CompressionType.BLOCK);
        job.setPartitionerClass(TotalOrderPartitioner.class);


        InputSampler.Sampler<IntWritable, Text> sampler =
                new InputSampler.RandomSampler<IntWritable, Text>(0.1, 1000, 10);


        InputSampler.writePartitionFile(job, sampler);
        String partitionFile = TotalOrderPartitioner.getPartitionFile(conf);
        URI partitionUri = new URI(partitionFile + "#" + TotalOrderPartitioner.DEFAULT_PATH);
        DistributedCache.addCacheFile(partitionUri, conf);
        DistributedCache.createSymlink(conf);


        return job.waitForCompletion(true) ? 0 : 1;
    }


    public static void main(String[] args) throws Exception {
        int run = ToolRunner.run(new MissingTemperatureFields_new_version(), args);
        System.exit(run);
    }


}

hadoop权威指南  page= 297 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值