2021-01-31 大数据课程笔记 day11

时间煮雨
@R星校长

在这里插入图片描述

课程内容

mapreduce 原语(独创)

mapreduce 工作流程(重点)

MR 作业提交流程(重点)

YARN RM-HA 搭建(熟练)

运行自带的 wordcount(了解)

动手写 wordcount(熟练)

MapReduce 概述

Google 发表了两篇论文《Google File System》 《Google MapReduce》

《Google File System》简称 GFS,是 Google 公司用于解决海量数据存储的文件系统。

《Google MapReduce》简称 MapReduce , 是 Google 的计算框架,基于 GFS。

Map 映射

Reduce 汇聚、缩减

目标:普通人都能理解的理论基础

比如:如何统计北京一共有多少栋楼房?

源数据:

Haidian 200  Haidian 230  Haidian 200  Haidian 230
Haidian 300   Haidian 330 
Haidian 400   Haidian 420 
Haidian 500   Haidian 540 
Haidian 600   Haidian 120 
Map->
Haidian  200
Haidian 230
Haidian  200
Haidian   200,300,400,230,600

Reducer:
 Haidian  sum

在这里插入图片描述

原语:<<相同的 key 为一组,这一组数据调用一次 reduce 方法 , 方法内迭代计算这一组数据>>

Map-Reduce: 线性依赖关系,先执行完 map , 再执行 reduce

MapTask:
 映射: 保证原语中组的实现
 并行度: split
  split: 大小可调整,默认等于 hdfs 中 block 的大小
  框架默认 , hdfs 一个文件多少个 block , 就会有多少个 map
 计算级别: split 中一条记录 (record) 调用一次 map 方法!
ReduceTask:
 汇聚:
 计算级别:按照组 group 为单位,一组调用一次 reduce 方法!
 并行度:
  理想状态:多少组 group 对应多少个 reduceTask
  但是,其实一个 reduceTask 可以线性处理若干组

术语对比关系:
 • block > split
   – 1:1(默认)
   – N:1
   – 1:N
 • split > map
   – 1:1
 • map > reduce
   – N:1
   – M:N
   – 1:1
   – 1:N
 • group(key)>partition(redues task) reduce(){}
   – 1:1
   – N:1
   – M:N
   – 1:N? >违背了原语
 • partition > outputfile

1、每个 block 会有 map 任务
2、block 切分为切片,每个切片对应一个 map 任务,默认一个 block 一个切片,一个 map
3、map 默认按行读取切片数据,组成键值对 <当前行字节偏移量, “读到的行字符串”>
4、map 函数对该键值对进行计算,输出若干键值对。<key, value, partition>
partition 指定该键值对由哪个 reducer 进行处理
5、map 输出的 kvp 写到环形缓冲区,环形缓冲区默认 100MB ,阈值 80% ,当环缓达到 80% 就向磁盘溢写小文件,该小文件首先按照分区号排序,相同分区号的按 key 进行排序。
6、默认如果落磁盘的小文件达到了 3 个,则进行归并,归并的大文件也是按分区号排序,相同分区号按照 key 进行排序。只是一个归并。
7、如果 map 任务处理完了,它的输出被下载到 reducer 所在主机
按照 HTTP GET 的方式下载到 reducer:
reducer 发送 HTTP GET 请求到 mapper 主机下载数据,该过程是洗牌 shuffle
8、每个 map 任务都要经历运行结束洗牌的过程
9、可以设置 combinClass ,先在 map 端对数据进行一个压缩,比如 10w 个 <hello,1> 压缩为 1 个 <hello, 10w> 通过网络IO洗牌,肯定要快很多。一般情况下,combineClass 就是一个 reducerClass 。

开阔眼界:

尽管 hadoop 框架是 java 开发的, MapReduce 应用不一定得 java 开发。hadoop streaming 允许用户使用可执行文件的方式提供 mapper 和 reducer ,创建和执行作业。hadoop pipes 是一个跟 SWIG 兼容的 C++ API ,用于开发 MapReduce 应用(不基于 JNI )。

mapreduce 工作流程

官方给的定义:系统执行排序、将 map 输出作为输入传给 reducer 的过程称为 Shuffle 。(看完是不是一脸懵逼)通俗来讲,就是从 map 产生输出开始到 reduce 消化输入的整个过程称为 Shuffle 。如下图用黑线框出的部分:
在这里插入图片描述
圆形缓冲区介绍:
在这里插入图片描述

每一个 map 任务都会有一个圆形缓冲区。默认大小 100MB( io.sort.mb 属性 )阈值 0.8 也就是 80MB ( mapreduce.map.sort.spill.percent 属性指定 ) ,
在这里插入图片描述
一旦达到阈值一个后台线程开始把内容写到 (spill) 磁盘的指定目录 mapred.local.dir 下的新建的一个溢出写文件。写入磁盘前先 partition、sort、[combiner]。一个 map task 任务可能产生 N 个磁盘文件。 map task 运算完之后,产生了 N 个文件,然后将这些文件 merge 合成一个文件。
如果 N=2 ,合成的新文件写入磁盘前只经过 patition(分区)和 sort(排序)过程,不会执行 combiner 合并(无论是否指定 combiner 类),如下图所示:
在这里插入图片描述
如果 N>=3,合成的新文件写入磁盘前经过 patition(分区)、sort(排序)过和 combiner 合并(前提是指定了 combiner 类),如下图所示:
在这里插入图片描述

思考:为什么只有当 N>=3 时,合成文件才会执行 combiner 呢?

这是因为如果 N<3 时,执行 combiner 虽然减少了文件的大小,但是同时产生了一定的系统开销。由于减少的文件大小不大,权衡利弊后,确定 N<2 时不在执行 combiner 操作。当该 map task 全部执行完之后,对应的 reduce task 将会拷贝对应分区的数据(该过程称为 fetch),如下图所示:
在这里插入图片描述
其它的 map task 任务完成后,对应的 reduce task 也同样执行 fetch 操作,如下图所示:
在这里插入图片描述
每个 map 任务的完成时间可能不同,因此只要有一个任务完成,reduce 任务就开始复制其输出。该阶段被称为 reduce 的复制阶段。reduce 任务有少量复制线程,因此能够并行取得 map 输出。默认值是 5 个线程,但这个默认值可以通过设置 mapred.reduce.parallel.copies 属性改变。
在这里插入图片描述
复制完所有 map 输出后,reduce 任务进入合并阶段,该阶段将合并 map 输出,并维持其顺序排序(相当于执行了 sort),如果指定了 combiner,在写入磁盘前还会执行 combiner 操作。

那么具体是如何合并的呢?

合并因子默认是 10,可以通过 io.sort.factor 属性设置。合并过程是循环进行了,可能叫经过多趟合并。目标是合并最小数量的文件以便满足最后一趟的合并系数。假设有 40 个文件,我们不会在四趟中每趟合并 10 个文件从而得到 4 个文件。相反,第一趟只合并 4 个文件,随后的三趟分别合并 10 个文件。再最后一趟中 4 个已合并的文件和余下的 6 个(未合并的)文件合计 10 个文件。具体流程如下图所示:
在这里插入图片描述
注意:这并没有改变合并次数,它只是一个优化措施,目的是尽量减少写到磁盘的数据量,因为最后一趟总是直接合并到 reduce。
看到这里您是否理解了 Shuffle 的具体原理呢,如果没有,也没有关系,接下来我们通过一个 wordcount 案例再将整个流程梳理一遍。首先 map 任务的代码如下:

package cn.geekmooc;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class WCMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
   
	public void map(LongWritable ikey, Text ivalue, Context context) throws IOException, InterruptedException {
   
		String line = ivalue.toString();
		String words[] = line.split(" ");
		for (String word : words) {
   
			context.write(new Text(word), new LongWritable(1));
		}
	}
}

在这里插入图片描述
在分区(分区规则:按首字母分四个区,分别为 a-i , j-q , r-z , 其它)的过程中,会将相同的单词合并到一起,将出现次数用逗号隔开,如上图所示。注意此时还没有排序。分区代码如下:

package cn.geekmooc;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
public class WCPatitioner extends Partitioner<Text, LongWritable> {
   
	@Override
	public int getPartition(Text key, LongWritable value, int numPartitions) {
   
		int first_char = key.charAt(0);
		if(first_char>=97&&first_char<=105){
   //a- j
			return 0;
		}else if(first_char>=106&&first_char<=113){
   //k-q
			return 1;
		}else if(first_char>=114&&first_char<=122){
   //r-  z
			return 2;
		}else{
   
			
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值