MapReduce之数据组织模式

本文深入探讨了Hadoop中二次排序的实现原理,包括分区、排序及二次排序的具体操作过程。通过实例展示了如何通过自定义mapper、partitioner、comparator和reducer来实现对数据的精确控制和高效处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分区:默认情况下一个分区对应一个reducer,也就是有几个分区就会有几个part-0,part-1,part-2...的输出结果在hdfs上

排序:有三次,每个maper的中间结果是有序的(走两遍排序),每个reducer合并完mapper的中间结果后是有序的(每个分区再走一遍排序)

二次排序的案例

1、输入数据

4 1
5 1
6 4
7 4
4 1
5 1
6 4
7 4
4 1
5 1
6 4
7 4
4 1
5 1
6 4
7 4

2、mapper

public class TwriceSortMapper extends Mapper<LongWritable, Text, Text, Text> {

    //long、String不能在hadoop之间进行数据传输,所以必须使用hadoop提供的序列化方法long=>longWriable、String=>Text
    @Override
    protected void map(LongWritable key, Text value,
                       org.apache.hadoop.mapreduce.Mapper.Context context)
            throws IOException, InterruptedException {

            context.write(value, value);
    }
}

2、patitioner

当numReduceTasks=1时,所有数据都在一个分区里

当numReduceTasks=4时,所有4 1在一个分区,所有5  2在一个分区,所有6 3在一个分区,所有7 4在一个分区

public class KeyPartitioner extends Partitioner<Text, Text> {

    @Override
    public int getPartition(Text key, Text value,int numReduceTasks){
        return (key.toString().split(" ")[0].hashCode()&Integer.MAX_VALUE)%numReduceTasks;
    }
}

3、sort    

//对键值对的key进行排序
public class SortComparator extends WritableComparator {

    protected SortComparator(){
        super(Text.class,true);
    }

    @Override
    public int compare(WritableComparable key1, WritableComparable key2){
        if(Integer.parseInt(key1.toString().split(" ")[0])==Integer.parseInt(key2.toString().split(" ")[0])){
            if(Integer.parseInt(key1.toString().split(" ")[1])>Integer.parseInt(key2.toString().split(" ")[1])){
                return 1;
            }else if (Integer.parseInt(key1.toString().split(" ")[1])<Integer.parseInt(key2.toString().split(" ")[1])){
                return -1;
            }else if(Integer.parseInt(key1.toString().split(" ")[1])==Integer.parseInt(key2.toString().split(" ")[1])) {
                return 0;
            }
        }else {
            if(Integer.parseInt(key1.toString().split(" ")[0])>Integer.parseInt(key2.toString().split(" ")[0])){
                return 1;
            }else if(Integer.parseInt(key1.toString().split(" ")[0])<Integer.parseInt(key2.toString().split(" ")[0])){
                return -1;
            }
        }
        return 0;
    }

}

4、reducer

public class TwriceSortReducer  extends Reducer<Text, Text, NullWritable, Text> {

    @Override
    protected void reduce(Text key, Iterable<Text> v2s,Context context)
            throws IOException, InterruptedException {
        for (Text value :v2s) {
            context.write(NullWritable.get(),value);
        }
    }


}

5、main,reducer个数是1

public class TwriceSortMain {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        //构建job对象
        Job job = Job.getInstance(new Configuration());

        //注意:main方法所在的类
        job.setJarByClass(TwriceSortMain.class);

        //设置mapper相关属性
        job.setMapperClass(TwriceSortMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
//        FileInputFormat.setInputPaths(job, new Path("D:words.txt"));

        job.setSortComparatorClass(SortComparator.class);
        //设置reducer相关属性
        job.setReducerClass(TwriceSortReducer.class);
        job.setPartitionerClass(KeyPartitioner.class);
        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(Text.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        job.setNumReduceTasks(1);

//        FileOutputFormat.setOutputPath(job, new Path("D:wcout510"));


        //提交任务
        job.waitForCompletion(true);
    }

}

6、输出结果和解释

当numReduceTasks=1时,所有数据都在一个分区里

当numReduceTasks=4时,所有4 1在一个分区,所有5  2在一个分区,所有6 3在一个分区,所有7 4在一个分区

最终每个分区对一个reducer和part-r-00001,2,3,每个分区一个二次排序

4 1
4 1
4 1
5 1
5 1
5 1
6 4
6 4
6 4
7 4
7 4
7 4
7 4

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值