大数据——MapReduce基础(MapReduce概念)

MapReduce概念

        Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架;
        Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上。

1.1 为什么要MapReduce
  1. 海量数据在单机上处理因为硬件资源限制,无法胜任
  2. 而一旦将单机版程序扩展到集群来分布式运行,将极大增加程序的复杂度和开发难度
  3. 引入mapreduce框架后,开发人员可以将绝大部分工作集中在业务逻辑的开发上,而将分布式计算中的复杂性交由框架来处理。
  4. mapreduce分布式方案考虑的问题
    (1)运算逻辑要不要先分后合?
    (2)程序如何分配运算任务(切片)?
    (3)两阶段的程序如何启动?如何协调?
    (4)整个程序运行过程中的监控?容错?重试?
            分布式方案需要考虑很多问题,但是我们可以将分布式程序中的公共功能封装成框架,让开发人员将精力集中于业务逻辑上。而mapreduce就是这样一个分布式程序的通用框架。
1.2 MapReduce核心思想

在这里插入图片描述

1.3 MapReduce进程

一个完整的mapreduce程序在分布式运行时有三类实例进程:
(1)MrAppMaster:负责整个程序的过程调度及状态协调
(2)MapTask:负责map阶段的整个数据处理流程
(3)ReduceTask:负责reduce阶段的整个数据处理流程

1.4 MapReduce编程规范(八股文)

用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端)

  • 1)Mapper阶段

    (1)用户自定义的Mapper要继承自己的父类
    (2)Mapper的输入数据是KV对的形式(KV的类型可自定义)
    (3)Mapper中的业务逻辑写在map()方法中
    (4)Mapper的输出数据是KV对的形式(KV的类型可自定义)
    (5)map()方法(maptask进程)对每一个<K,V>调用一次

  • 2)Reducer阶段

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

  • 3)Driver阶段
    (1)整个程序需要一个Drvier来进行提交,提交的是一个描述了各种必要信息的job对象

  • 案例实操

    需求统计一堆文件中单词出现的个数(WordCount)。
    准备工作:
    (1)开启集群
    (2)准备数据
    步骤一:
    创建WordCountMapper类,继承Mapper类,实现map()方法。
    参数说明:
    (1)第一个:输入数据的行号
    (2)第二个:输入数据每一行的信息类型
    (3)第三个:输出的key类型
    (4)第四个:输出的value类型

     import org.apache.hadoop.io.IntWritable;
     import org.apache.hadoop.io.LongWritable;
     import org.apache.hadoop.io.Text;
     import java.io.*;
     import org.apache.hadoop.mapreduce.Mapper;
     
     /**
      * KEYIN 输入数据key 行数 VALUEIN 每一行的数据 KEYOUT输出数据 VALUEOUT输出数据的数量
      * 
      * @author lenovo
      * 
      */
     public class WordCountMapper extends
     		Mapper<LongWritable, Text, Text, IntWritable> {
    
     	    	protected void map(LongWritable key, Text value, Context context)
     	    			throws IOException, InterruptedException {
     	    
     	    		//获取第一行数据
     	    		String line = value.toString();
     	    		//获取每一个单词
     	    		String[] words = line.split(" ");
     	    		for (String word : words) {
     	    			//输出单词
     	    			context.write(new Text(word), new IntWritable(1));
     	    		}
     		}
      }
    

步骤二:
创建WordCountReduce类,继承Reduce类,实现reduce()方法。
参数说明:
(1)第一个:输入数据的key
(2)第二个:输入数据信息类型(和mapper中的输出类型一致)
(3)第三个:输出的key类型
(4)第四个:输出的value类型

import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class WordCountReduce extends Reducer<Text,IntWritable, Text, IntWritable>{


	protected void reduce(Text key, Iterable<IntWritable> values, Context context) 
			throws IOException ,InterruptedException {
		//统计所有单词个数
		int count = 0;
		for (IntWritable value : values) {
			count += value.get();
		}
		//输出所有单词个数
		context.write(key, new IntWritable(count));
	}
}

步骤三:
创建WordCountDriver类。

	import java.io.IOException;

	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.lib.input.FileInputFormat;
	import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

	public class WordCountDriver {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws IllegalArgumentException 
	 * @throws InterruptedException 
	 * @throws ClassNotFoundException 
	 */
		public static void main(String[] args) 
				throws IllegalArgumentException, IOException, ClassNotFoundException, InterruptedException {
			//1.获取job对象
			Configuration conf = new Configuration();
			Job job = Job.getInstance(conf);
			//2。设置加载jar包位置
			job.setJarByClass(WordCountDriver.class);
			//3。设置map和reduce的class
			job.setMapperClass(WordCountMapper.class);
			job.setReducerClass(WordCountReduce.class);
			//4.设置输出mapper的数据类型
			job.setMapOutputKeyClass(Text.class);
			job.setMapOutputValueClass(IntWritable.class);
			//5.设置最终数据输出的类型
			job.setOutputKeyClass(Text.class);
			job.setOutputValueClass(IntWritable.class);
			//6.设置输入数据和输出数据的路径
			FileInputFormat.setInputPaths(job, new Path(args[0]));
			FileOutputFormat.setOutputPath(job, new Path(args[1]));
			//7.提交
			//job.submit();
			boolean result = job.waitForCompletion(true);
			System.exit(result ? 0 : 1);
		}
}

步骤四:将程序打成jar包,然后拷贝到hadoop集群中。
步骤四:执行wordcount程序
[root@hadoop hadoop-2.7.2]# hadoop jar wc.jar bh.shy.wordcount.WordcountDriver /user/shy/input /user/shy/output1

1.5 MapReduce程序运行流程分析

在这里插入图片描述
(1)在MapReduce程序读取文件的输入目录上存放相应的文件。
(2)客户端程序在submit()方法执行前,获取待处理的数据信息,然后根据集群中参数的配置形成一个任务分配规划。
(3)客户端提交job.split、jar包、job.xml等文件给yarn,yarn中的resourcemanager启动MRAppMaster。
(4)MRAppMaster启动后根据本次job的描述信息,计算出需要的maptask实例数量,然后向集群申请机器启动相应数量的maptask进程。
(5)maptask利用客户指定的inputformat来读取数据,形成输入KV对。
(6)maptask将输入KV对传递给客户定义的map()方法,做逻辑运算
(7)map()运算完毕后将KV对收集到maptask缓存。
(8)maptask缓存中的KV对按照K分区排序后不断写到磁盘文件
(9)MRAppMaster监控到所有maptask进程任务完成之后,会根据客户指定的参数启动相应数量的reducetask进程,并告知reducetask进程要处理的数据分区。
(10)Reducetask进程启动之后,根据MRAppMaster告知的待处理数据所在位置,从若干台maptask运行所在机器上获取到若干个maptask输出结果文件,并在本地进行重新归并排序,然后按照相同key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算。
(11)Reducetask运算完毕后,调用客户指定的outputformat将结果数据输出到外部存储。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值