本文已参加「新人创作礼」活动,一起开启掘金创作之路。
这次带来的是大数据框架基础: 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 |
| 示例输出 | |
|---|---|
| hello | 2 |
| hi | 1 |
| name | 1 |
| there | 2 |
| what's | 1 |
解析
我们可以利用 Intellij IDEA 编写好可执行相关操作的代码,导入 Linux 生成 jar 文件。
创建 word.txt 文件,并上传至 hdfs 文件系统
使用 MapReduce 对文件进行处理
得到结果
具体实现代码
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);
}
}
}
}