基础:MapReduce 实践

189 阅读2分钟

本文已参加「新人创作礼」活动,一起开启掘金创作之路。

这次带来的是大数据框架基础: MapReduce 的简单实践。

如果想要学习 MapReduce ,单词计数实践一定是我们的首选,人送外号:MapReduce 版 “ Hello World ”。

概念

对于 map

  • 读取文件每一行的内容,并将其解析成 key、value 对

  • 对 key、value 进行处理,转换成自己所需要的输出

  • 分区

  • 对不同分区的数据,依据自己的目标进行处理。在这里是按照 key 进行排序、分组,将相同 key 的 value 放到一个集合中

对于 reduce

  • 按照不同的分区,通过网络将 map 的输出复制到不同的 reduce 节点中

  • 对 map 的输出结果进行处理,转换成自己所需要的输出

  • 将 reduce 的输出保存到文件中

目标

l  简单掌握基本的 MapReduce 思想;

l  掌握用 MapReduce 解决基本问题如 单词计数 等。

环境

l  操作系统:Linux(建议Ubuntu16.04)

l  Hadoop版本:2.7.1

操作

使用 MapReduce 对单词数进行计数。

示例输入
There
There
hello
hello
hi 
name
there
what's
your
示例输出
hello2
hi1
name1
there2
what's1

解析

我们可以利用 Intellij IDEA 编写好可执行相关操作的代码,导入 Linux 生成 jar 文件。

image.png

image.png

创建 word.txt 文件,并上传至 hdfs 文件系统

image.png

使用 MapReduce 对文件进行处理

image.png

得到结果

image.png  

具体实现代码

import java.io.IOException;

import java.util.Iterator;

import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.util.GenericOptionsParser;

 

public class WordCount {

    public WordCount() {

    }

 

    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();

        String[] otherArgs = (new GenericOptionsParser(conf, args)).getRemainingArgs();

        if(otherArgs.length < 2) {

            System.err.println("Usage: wordcount <in> [<in>...] <out>");

            System.exit(2);

        }

 

        Job job = Job.getInstance(conf, "word count");

        job.setJarByClass(WordCount.class);

        job.setMapperClass(WordCount.TokenizerMapper.class);

        job.setCombinerClass(WordCount.IntSumReducer.class);

        job.setReducerClass(WordCount.IntSumReducer.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

 

        for(int i = 0; i < otherArgs.length - 1; ++i) {

            FileInputFormat.addInputPath(job, new Path(otherArgs[i]));

        }

 

        FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1]));

        System.exit(job.waitForCompletion(true)?0:1);

    }

 

    public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

        private IntWritable result = new IntWritable();

 

        public IntSumReducer() {

        }

 

        public void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {

            int sum = 0;

 

            IntWritable val;

            for(Iterator i$ = values.iterator(); i$.hasNext(); sum += val.get()) {

                val = (IntWritable)i$.next();

            }

 

            this.result.set(sum);

            context.write(key, this.result);

        }

    }

 

    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {

        private static final IntWritable one = new IntWritable(1);

        private Text word = new Text();

 

        public TokenizerMapper() {

        }

 

        public void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {

            StringTokenizer itr = new StringTokenizer(value.toString());

 

            while(itr.hasMoreTokens()) {

                this.word.set(itr.nextToken());

                context.write(this.word, one);

            }

 

        }

    }

}