Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。
Mapreduce核心巩固是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算框架,并发运行在一个Hadoop集群上
1)分布式的运算程序往往需要分成至少2个阶段。
2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。
3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
4)MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
总结:分析WordCount数据流走向深入理解MapReduce核心思想。
一个完整的MapReduce程序在分布式运行时有三类实例进程:
Mr AppMaster : 负责整个程序的过程调度及状态协调。
MapTask : 负责Map阶段的整个数据处理流程。
ReduceTask : 负责Reduce阶段的整个数据处理流程。
Java类型 | Hadoop Writable类型 |
---|---|
boolean | BooleanWritable |
byte | ByteWritable |
int | IntWritable |
float | FloatWritable |
long | LongWritable |
double | DoubleWritable |
String | Text |
map | MapWritable |
array | ArrayWritable |
用户编写的程序分成三个部分:Mapper、Reducer和Driver。
Mapper阶段
(1)用户自定义的Napper要继承自己的父类
(2) Npprp输入数据是Kv对形式(KvV的类型可自定义
(3) Napper中的业务逻相写在mp0方法中.
(4) Mpprg输出数据是KV对研式(EV9类型可自定义)(5) mp0方法(NmpTaxk进程)对每一个KV>调用一-次
Reducer阶段
(1)用户自定义的Reducer要继承自己的父类
(2) Reducer的输入数据类型对应Mapper的输出数据类型,也是KV
(3) Reducer的业务逻辑写在reduce(方法中
(4) Reduce Task进程对每-组相同k的
Driver阶段
相当于YARN集群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了MapReduce程序相关运行参数的job对象
在给定的文本文件中统计输出每一个单词出现的总次数
例如wc.txt
spark,hadoop,flink
kafka,hbase
hive,kafka
hbase,oozie
sqoop,hadoop
hadoop,java,scala
期望输出数据
flink 1
hadoop 3
hbase 2
hive 1
java 1
kafka 2
oozie 1
scala 1
spark 1
sqoop 1
环境准备
(1) 在pom.xml文件中添加如下依赖
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>RELEASEversion>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.8.2version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-commonartifactId>
<version>2.7.2version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-clientartifactId>
<version>2.7.2version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-hdfsartifactId>
<version>2.7.2version>
dependency>
dependencies>
(2)在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入。
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
(3) 添加打包集群依赖
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>2.3.2version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
<plugin>
<artifactId>maven-assembly-plugin artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependenciesdescriptorRef>
descriptorRefs>
<archive>
<manifest>
<mainClass>com.huan.wc.DrivermainClass>
manifest>
archive>
configuration>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
编写Mapper类
//Map阶段
//KEYIN 输入数据的key (长度)
//VALUEIN 输入数据的value (值)
//KEYOUT 输出数据的key
//VALUEOUT 输出数据的Value类型
public class MyMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
Text k = new Text();
IntWritable v = new IntWritable();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//TODO 获取一行一行数据
String line = value.toString();
//TODO 切割单词
String[] splits = line.split( "," );
//TODO 循环遍历 并写出
for (String split : splits) {
//TODO
k.set( split );
v.set( 1 );
context.write( k,v );
}
}
}
编写Reduce类
//KEYINT map端的KEYOUT
//VALUEINT map端的VALUEOUT
public class MyReduce extends Reducer<Text, IntWritable,Text, IntWritable> {
IntWritable v = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
//TODO 累加求和
for (IntWritable value : values) {
//TODO 获取value
int i = value.get();
sum += i;
}
v.set( sum );
context.write( key,v );
}
}
编写Driver类
public class Driver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//TODO 获取job任务
Configuration conf = new Configuration();
Job job = Job.getInstance( conf );
//TODO 设置jar存储位置
job.setJarByClass(Driver.class );
//TODO 关联Map和Reduce
job.setMapperClass( MyMapper.class );
job.setReducerClass( MyReduce.class );
//TODO 设置Mapper阶段输出数据的key和value类型
job.setMapOutputKeyClass( Text.class );
job.setMapOutputValueClass( IntWritable.class );
//TODO 设置最终数据输出的key和value类型
job.setOutputKeyClass( Text.class );
job.setOutputValueClass( IntWritable.class );
//TODO 设置输入路径和输出路径
FileInputFormat.setInputPaths( job,new Path( args[0] ) );
FileOutputFormat.setOutputPath( job,new Path( args[1] ) );
//TODO 提交job
boolean result = job.waitForCompletion( true );
System.exit( result ? 0 : 1 );
}
}
开始打包jar
(1)将打包好的jar放入hadoop集群中
(2)启动hadoop集群
(3)执行WordCount程序
[root@huan01 hadoop]# hadoop jar wc.jar com.huan.wc.Driver /huan/input/wc.txt /huan/output1
结果为
[root@huan03 ~]# hadoop fs -cat /huan/output1/part-r-00000
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/hadoop/hadoop-2.7.2/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/hbase/hbase/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
flink 1
hadoop 3
hbase 2
hive 1
java 1
kafka 2
oozie 1
scala 1
spark 1
sqoop 1