Hadoop框架之——Mapreduce概述

1.定义

Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。

Mapreduce核心巩固是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算框架,并发运行在一个Hadoop集群上

2.优缺点

2.1.优点

  • mapreduce易于编程
    它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的PC机器上运行,也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的,就是因为这个特点使得Mapreduce编程变得非常流行
  • 良好的扩展性
    当你的计算机资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力
  • 高容错性
    Mapreduce的初衷就是使程序能够部署在廉价的PC的机器上,这就要求它具有很高的容错性,比如其中一台机器挂了,它可以把上面的计算任务转移到另一个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工的参与,而完全是由Hadoop内部完成的
  • 适合PB级以上海量数据的离线处理
    可以实现千台服务器集群的并发工作,提供数据处理能力

2.2缺点

  • 不擅长实时计算
    MapReduce无法像MySQL-样,在亳秒或者秒级内返回结果。
  • 不擅长流式计算
    流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态变化。这是因为MapReduce日自 身的设计特点决定了数据源必须是静态的。
  • 不擅长DAG (有向图)计算
    多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。 在这种情况下,MapReduce并不是 不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘,会造成大量的磁盘I0,导致性能非常的低下。

3,MapReduce核心思想

在这里插入图片描述
1)分布式的运算程序往往需要分成至少2个阶段。
2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。
3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
4)MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
总结:分析WordCount数据流走向深入理解MapReduce核心思想。

4, MapReduce进程

一个完整的MapReduce程序在分布式运行时有三类实例进程:

  1. Mr AppMaster : 负责整个程序的过程调度及状态协调。

  2. MapTask : 负责Map阶段的整个数据处理流程。

  3. ReduceTask : 负责Reduce阶段的整个数据处理流程。

5,常用数据序列化类型

Java类型Hadoop Writable类型
booleanBooleanWritable
byteByteWritable
intIntWritable
floatFloatWritable
longLongWritable
doubleDoubleWritable
StringText
mapMapWritable
arrayArrayWritable

6,MapReduce编程规范

用户编写的程序分成三个部分:Mapper、Reducer和Driver。

  1. Mapper阶段
    (1)用户自定义的Napper要继承自己的父类
    (2) Npprp输入数据是Kv对形式(KvV的类型可自定义
    (3) Napper中的业务逻相写在mp0方法中.
    (4) Mpprg输出数据是KV对研式(EV9类型可自定义)(5) mp0方法(NmpTaxk进程)对每一个KV>调用一-次

  2. Reducer阶段
    (1)用户自定义的Reducer要继承自己的父类
    (2) Reducer的输入数据类型对应Mapper的输出数据类型,也是KV
    (3) Reducer的业务逻辑写在reduce(方法中
    (4) Reduce Task进程对每-组相同k的<k,v> 组调用- -次reduce0方法

  3. Driver阶段
    相当于YARN集群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了MapReduce程序相关运行参数的job对象

7. WordCount案例实操

在给定的文本文件中统计输出每一个单词出现的总次数
例如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>junit</groupId>
			<artifactId>junit</artifactId>
			<version>RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.8.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-common</artifactId>
			<version>2.7.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-client</artifactId>
			<version>2.7.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-hdfs</artifactId>
			<version>2.7.2</version>
		</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-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-assembly-plugin </artifactId>
				<configuration>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
					<archive>
						<manifest>
						<!--注意:这理需要替换为自己工程主类-->
							<mainClass>com.huan.wc.Driver</mainClass>
						</manifest>
					</archive>
				</configuration>
				<executions>
					<execution>
						<id>make-assembly</id>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值