使用MapReduce进行二次排序

首先进行hadoop集群的hdfs,yarn等的相关配置,配置成功之后。进行如下操作:

1 启动Hadoop

执行命令启动前面实验部署好的Hadoop系统。

[root@master ~]# cd /usr/cstor/hadoop/

[root@master hadoop]# sbin/start-all.sh

使用jps 分别查看masterJava进程如下:

使用jps 分别查看其他slave1-4服务器上Java进程如下:

有如上信息说明Hadoop集群搭建成功。

停止进程操作:

扫描二维码关注公众号,回复: 8815156 查看本文章

[root@master ~]# cd /usr/cstor/h

hadoop/ hbase/  hive/  

[root@master ~]# cd /usr/cstor/hadoop

[root@master hadoop]# cd sbin

[root@master sbin]# ll

[root@master sbin]# ./stop-all.sh

2.1 验证HDFS上没有/user/mapreduce/secsort/in的文件夹

[root@master ~]# cd /usr/cstor/hadoop/

[root@master hadoop]# bin/hadoop fs -ls /                    #查看HDFS上根目录文件 /

此时HDFS上应该是没有/user/mapreduce/secsort/in文件夹。

2.2 准备数据

输入数据如下:secsortdata.txt ('\t'分割)(数据放在/root/data/6目录下):

查看数据如下:

注意:这里之前如果没有数据文件的话需要使用远程连接的文件传输工具xftp或者其他进行数据文件的上传。

2.3 上传数据文件到HDFS

(1)新建上传路径

使用[root@master ~]# hdfs dfs -ls /查看没有发现有路径,则需要新建上传的路径[root@master ~]# hdfs dfs -mkdir -p /user/mapreduce/secsort/in 。

查看结果如下:

可以看到输入路径已经存在。

(注:这里的输入路径由于可以自由指定)

(2)上传数据文件到/user/mapreduce/secsort/in下。

[root@master ~]# hdfs dfs -put /root/data/6/secsortdata.txt /user/mapreduce/secsort/in

查看数据文件:

[root@master ~]# hdfs dfs -ls -R /

查看数据文件存在于该目录下即为上传成功。

3 编写IntPair程序

首先在eclipse上新建名为SecondarySort的java工程文件,然后新建类IntPair将其放在包mr的下面。

IntPair类用于数据的存储,并在IntPair类内部自定义Comparator类以实现第一字段和第二字段的比较。实现排序的功能。

程序如下:

IntPair 类:
package mr;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.WritableComparable;

public class IntPair implements WritableComparable {
    private IntWritable first;
    private IntWritable second;
    public void set(IntWritable first, IntWritable second) {
        this.first = first;
        this.second = second;
    }
    //注意:需要添加无参的构造方法,否则反射时会报错。
    public IntPair() {
        set(new IntWritable(), new IntWritable());
    }
    public IntPair(int first, int second) {
        set(new IntWritable(first), new IntWritable(second));
    }
    public IntPair(IntWritable first, IntWritable second) {
        set(first, second);
    }
    public IntWritable getFirst() {
        return first;
    }
    public void setFirst(IntWritable first) {
        this.first = first;
    }
    public IntWritable getSecond() {
        return second;
    }
    public void setSecond(IntWritable second) {
        this.second = second;
    }
    public void write(DataOutput out) throws IOException {
        first.write(out);
        second.write(out);
    }
    public void readFields(DataInput in) throws IOException {
        first.readFields(in);
        second.readFields(in);
    }
    public int hashCode() {
        return first.hashCode() * 163 + second.hashCode();
    }
    public boolean equals(Object o) {
        if (o instanceof IntPair) {
            IntPair tp = (IntPair) o;
            return first.equals(tp.first) && second.equals(tp.second);
        }
        return false;
    }
    public String toString() {
        return first + "\t" + second;
    }
    public int compareTo(IntPair tp) {
        int cmp = first.compareTo(tp.first);
        if (cmp != 0) {
            return cmp;
        }
        return second.compareTo(tp.second);
    }
}

注:程序非本人编写,来源于实验平台,这里只是记录一下所学知识。以方便自己和他人。

4 编写SecondarySort程序

在这个程序中定义了一个FirstPartitioner类,在FirstPartitioner类内部指定聚合规则为第一字段。实现聚合的功能。

此外,还需要开启MapReduce框架自定义Partitioner 功能和GroupingComparator功能。程序附在后面:

SecondarySort代码如下: 

package mr;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class SecondarySort {
    static class TheMapper extends Mapper<LongWritable, Text, IntPair, NullWritable> {
        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {
            String[] fields = value.toString().split("\t");
            int field1 = Integer.parseInt(fields[0]);
            int field2 = Integer.parseInt(fields[1]);
            context.write(new IntPair(field1,field2), NullWritable.get());
        }
    }
    static class TheReducer extends Reducer<IntPair, NullWritable,IntPair, NullWritable> {
        //private static final Text SEPARATOR = new Text("------------------------------------------------");
        @Override
        protected void reduce(IntPair key, Iterable<NullWritable> values, Context context)
                throws IOException, InterruptedException {
            context.write(key, NullWritable.get());
        }
    }
    public static class FirstPartitioner extends Partitioner<IntPair, NullWritable> {
        public int getPartition(IntPair key, NullWritable value,
                int numPartitions) {
            return Math.abs(key.getFirst().get()) % numPartitions;
        }
    }
    //如果不添加这个类,默认第一列和第二列都是升序排序的。
//这个类的作用是使第一列升序排序,第二列降序排序
    public static class KeyComparator extends WritableComparator {
        //无参构造器必须加上,否则报错。
        protected KeyComparator() {
            super(IntPair.class, true);
        }
        public int compare(WritableComparable a, WritableComparable b) {
            IntPair ip1 = (IntPair) a;
            IntPair ip2 = (IntPair) b;
            //第一列按升序排序
            int cmp = ip1.getFirst().compareTo(ip2.getFirst());
            if (cmp != 0) {
                return cmp;
            }
            //在第一列相等的情况下,第二列按倒序排序
            return -ip1.getSecond().compareTo(ip2.getSecond());
        }
    }
    //入口程序
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        job.setJarByClass(SecondarySort.class);
        //设置Mapper的相关属性
        job.setMapperClass(TheMapper.class);
        //当Mapper中的输出的key和value的类型和Reduce输出
//的key和value的类型相同时,以下两句可以省略。
        //job.setMapOutputKeyClass(IntPair.class);
        //job.setMapOutputValueClass(NullWritable.class);
        FileInputFormat.setInputPaths(job, new Path(args[0]));
        //设置分区的相关属性
        job.setPartitionerClass(FirstPartitioner.class);
        //在map中对key进行排序
        job.setSortComparatorClass(KeyComparator.class);
        //job.setGroupingComparatorClass(GroupComparator.class);
        //设置Reducer的相关属性
        job.setReducerClass(TheReducer.class);
        job.setOutputKeyClass(IntPair.class);
        job.setOutputValueClass(NullWritable.class);
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        //设置Reducer数量
        int reduceNum = 1;
        if(args.length >= 3 && args[2] != null){
            reduceNum = Integer.parseInt(args[2]);
        }
        job.setNumReduceTasks(reduceNum);
        job.waitForCompletion(true);
    }
}

5 打包程序

选择项目工程文件夹,右击选择“Export”进入如下界面:

选择JAR file ,点击“Next”进入如下界面:

选择图中箭头所指的文件和输出路径的位置,方便上传。

之后点击上面的“finish”即可完成打包,忽略警告信息即可。

6 运行程序

[root@master ~]# yarn jar SecondarySort.jar mr.SecondarySort  /user/mapreduce/secsort/in/secsortdata.txt /user/mapreduce/secsort/out

其中“yarn”为命令,“jar”为命令参数,后面紧跟打包后的代码地址,“mr.SecondarySort”为主类名,mr为包名,“/user/mapreduce/secsort/in/secsortdata.txt”为输入文件在HDFS中的位置,“/user/mapreduce/secsort/out”为输出文件在HDFS中的位置。“SecondarySort.jar ”打包时的名称。

出现如上信息即为运行成功。

出现的问题:

问题原因:在运行时出现了上述的版本不支持的问题,可以看出是由于java环境问题造成的,即为jdk版本不一致。

解决方法:修改项目的jdk版本:

7 查看运行结果

(1)在master服务器上查看

  [root@master ~]# hdfs dfs -ls /user/mapreduce/secsort/out

查看源文件,进行一个对比。

发现程序运行正确。

(2)登录http://10.30.68.6:8088/cluster查看运行状态

可以看见二次排序程序运行成功,也可以看见其运行时间。

说明:在本实验中的程序并非本人所写,这里只是记录一下实验的步骤以及过程,方便自己和他人使用。

实验时不仅要认真更要注意查看每一步的结果,出错时,要看错误信息,不懂可以上网查看。

发布了95 篇原创文章 · 获赞 22 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40371180/article/details/88773818
今日推荐