MapReduce 是一个分布式运算程序的编程框架,是用户开发基于Hadoop的数据分析应用的核心框架。
MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。
(1)MapReduce 易于编程
(2)良好的扩展性
(3)高容错性
(4)适合 PB 级别以上海量数据的离线处理
(1)不擅长实时计算
(2)不擅长流式计算
(3)不擅长DAG(有向无环图)计算
(1)分布式的运算程序往往需要分成至少2个阶段。
(2)第一个阶段的 MapTask 并发实例,完全并行运行,互不相干。
(3)第二个阶段的 ReduceTask 并发实例互不相干,但是他们的数据依赖于上一个阶段的所有 MapTask 并发实例的输出。
(4)MapReduce 编程模型只能包含一个 Map 阶段和一个 Reduce 阶段,如果用户的业务逻辑非常复杂,那就只能多个 MapReduce 程序,串行运行。
总结:分析 WordCount 数据流走向深入理解 MapReduce 核心思想。
一个完整的 MapReduce 程序在分布式运行时有三类实例进程:
(1)MrAppMaster:负责整个程序的过程调度及状态协调。
(2)MapTask:负责Map阶段的整个数据处理流程。
(3)ReduceTask:负责 Reduce 阶段的整个数据处理流程。
Java类型 | Hadoop Writable类型 |
---|---|
Boolean | BooleanWritable |
Byte | ByteWritable |
Int | IntWritable |
Float | FloatWritable |
Long | LongWritable |
Double | DoubleWritable |
String | Text |
Map | MapWritable |
Array | ArrayWritable |
Null | NullWritable |
Mapper 阶段
① 用户自定义的 Mapper 要继承自己的父类(Mapper);
② Mapper 的输入数据是 KV 键值对的形式(KV类型可自定义);
③ Mapper 中的业务逻辑写在 map() 方法中;
④ Mapper 的输出数据是 KV 键值对的形式(KV类型可自定义);
⑤ map() 方法(MapTask进程)对每一个
Reduce 阶段
① 用户自定义的 Reducer 要继承自己的父类(Reducer);
② Reducer 的输入数据类型对应 Mapper 的输出数据类型,也是KV;
③ Mapper 中的业务逻辑写在 reduce() 方法中;
④ ReduceTask 进程对每一组相同 K 的
Driver 阶段
(1)需求
在给定的文本文件中统计输出每一个单词出现的总次数
输入数据:hello.txt
java java
hadoop hadoop
shell shell
idea idea idea
xiao datenode namenode
hdfs yarn mapreduce
期望输出数据:
datenode 1
hadoop 2
hdfs 1
idea 3
java 2
mapreduce 1
namenode 1
shell 2
xiao 1
yarn 1
(2)需求分析
(3)环境准备
① 创建 Maven 工程
② 在在pom.xml文件中添加如下依赖
junit
junit
4.12
org.apache.logging.log4j
log4j-slf4j-impl
2.12.0
org.apache.hadoop
hadoop-client
3.1.3
③ 在项目的src/main/resources目录下,新建一个文件,命名为“log4j2.xml”,在文件中填入。
(4)编写程序
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
//设置需要输出的键值对类型
private Text outKey = new Text();
private IntWritable outValue = new IntWritable(1);//指定键值对的value值为1,后面方便计算
//重写map方法 快捷键(Ctrl + o)
//参数解读:1、偏移量 2、读取输入的一行数据(xiaoxq xiaoxq) 3、上下文对象
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//1.获取一行数据,并将其转换为字符串类型
String line = value.toString();
//2、将读取到的单词字符串进行切割,按照空格切割
String[] words = line.split(" ");
//3、写出
for (String word : words) {
//封装outKey,outValue
outKey.set(word);
//输出
context.write(outKey,outValue);
}
}
}
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
//设置输出的value的类型
private IntWritable outValue = new IntWritable();
//重写reduce方法
//参数解读:1、单词 2、相同单词的一组数据 3、上下文对象
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
//遍历单词进行统计计数
int sum = 0;
for (IntWritable value : values) {
int i = value.get();
sum += i;
}
//封装outValue
outValue.set(sum);
//输出
context.write(key,outValue);
}
}
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1、获取配置信息,获取job对象实例
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2、指定本程序的jar包所在的本地路径(设置本地Driver对象)
job.setJarByClass(WordCountDriver.class);
//3、关联 mapper 和 reducer 业务类对象
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4、设置 mapper 端的输出数据的 Key,Value 类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5、设置 MapReduce 程序的最终输出数据的 Key,Value 类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6、设置程序(job)的输入输出路径
FileInputFormat.setInputPaths(job, new Path("F:\\input\\inputword\\hello.txt"));
FileOutputFormat.setOutputPath(job, new Path("F:\\input\\MapReduce\\output3"));
//7、提交job作业
boolean b = job.waitForCompletion(true);
System.exit(b ? 0 : 1);
}
}
(5)本地测试
(1)需要首先配置好 HADOOP_HOME 变量以及 Windows 运行依赖
(2)在 IDEA/Eclipse 上运行程序
(6)集群上测试
(1)用maven打jar包,需要添加的打包插件依赖
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.6.1version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
<plugin>
<artifactId>maven-assembly-pluginartifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependenciesdescriptorRef>
descriptorRefs>
configuration>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
注意:如果工程上显示红叉。在项目上右键->maven->Reimport即可
(1)将程序打成jar包,然后拷贝到Hadoop集群中
步骤详情:右键->Run as->maven install。等待编译完成就会在项目的target文件夹中生成jar包。如果看不到。在项目上右键->Refresh,即可看到。修改不带依赖的jar包名称为wc.jar,并拷贝该jar包到Hadoop集群。
(2)启动Hadoop集群
(3)执行WordCount程序
[xiaoxq@hadoop105 software]$ hadoop jar wc.jar
com.xiaoxq.wordcount.WordcountDriver /user/xiaoxq/input /user/xiaoxq/output