1. MapReduce初识
本文开始我们学习hadoop的另一大组成部分:MapReduce
1.1 MapReduce定义
MapReduce是一个分布式运算程序的编程框架。
MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。
1.2 MapReduce优缺点
优点
- 易于编程:用户通过实现框架接口,只需关心业务逻辑
- 良好扩展性:可动态增加服务器,解决计算资源不够问题
- 高容错性:任何一台机器挂掉,可将任务转移到其他节点
- 适合海量数据计算(TB/PB): 千台服务器共同计算
缺点
- 不擅长实时计算
- 不擅长流式计算
- 不擅长DAG有向无环图计算
1.3 MapReduce核心编程思想
先了解下大概思想,下一篇文章我们通过wordcount具体案例来深入理解
- MapReduce运算程序一般分为两个阶段:Map阶段与Reduce阶段
- Map阶段的并发MapTask,完全并行运行,互不相干
- Reduce阶段的并发ReduceTask,完全并行运行,互不相干,但是数据依赖于上一阶段所有MapTask并发实例的输出
- MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行
我们通过一个具体的WordCount案例来进一步理解MapReduce
2. WordCount实践
2.1 新建模块hadoop,新增依赖配置
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.3.4</version>
</dependency>
</dependencies>
2.2 hadoop模块resouces目录下新建words.txt
shenjian suanfaxiaosheng
csdn wechat shenjian.online shenjian.online
wechat haotu369 suanfaxiaosheng csdn
2.3 新建WordCountMapper类
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
private Text keyOut = new Text();
private IntWritable valueOut = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
// words.txt中的每一行均会调用次map方法
String line = value.toString();
String[] words = line.split(" ");
for (String word : words) {
keyOut.set(word);
context.write(keyOut, valueOut);
}
}
}
2.4 新建WordCountReduce类
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class WordCountReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable valueOut = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
// 接收map阶段过来的信息,进行统计
int sum = 0;
for (IntWritable value : values) {
sum += value.get();
}
valueOut.set(sum);
context.write(key, valueOut);
}
}
2.5 新增WordCountDriver类
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.Job;
import java.io.IOException;
public class WordCountDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCountDriver.class);
job.setMapperClass(WordCountMapper.class);
job.setCombinerClass(WordCountReduce.class);
job.setReducerClass(WordCountReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
2.6 传参运行及结果查看
由于本地运行,写入绝对路径即可
E:\Java\blogCode\hadoop\src\main\resources\words.txt E:\Java\blogCode\hadoop\src\main\resources\words_ret.txt
结果如图所示
2.7 打包到集群上运行
- 对于之前的hadoop集群部署,我们修改下配置已使得可以WebUI直接可以上传,datanode放开9864端口,hostname设置为datanode,其他节点同理设置namenode等,最后我们在电脑hosts中配置域名对应IP即可
datanode:
ports:
- 9864:9864
hostname: datanode
- 我们上传words.txt文件至目录/shenjian/input中
- 在idea中package打包hadoop模块,目前集群支持jdk8,注意下版本,然后我们将打包好的jar包拷贝至namenode容器(当前容器id为b0f8a532e9452d51e5b49e97007ea087d36d887b99e2cd8f13bfb78802f4df7c)中
$ docker cp hadoop-1.0-SNAPSHOT.jar b0f8a532e9452d51e5b49e97007ea087d36d887b99e2cd8f13bfb78802f4df7c:/
- 最后我们进入namenode容器中运行
# hadoop jar hadoop-1.0-SNAPSHOT.jar online/shenjian/hadoop/WordCountDriver /shenjian/input/ /shenjian/output
欢迎关注公众号算法小生第一时间获取最新文章