mapreduce原理

MapReduce 计算思想:将串行计算变成并行计算,把大任务拆分成

很多个小任务,多个小任务同时执行得到局部的汇总结果,然后将

局部的结果汇总得出最终结果。

分布式计算:

引子:JDBC - MYSQL 两节点间传输数据 影响其速度的因素有:

1 磁盘IO 2 网络IO(更慢)

故本地传输数据是很快的;

移动数据-将数据移动到计算程序所在的节点上,然后进行计算;

移动计算-将计算程序移动到数据存储的节点上进行计算;

*当需要计算的数据量很大时,移动计算程序的代价较小,效率更高;

具体过程:MapReduce

第1阶段map:将计算程序打包并分发到各个DN,各个DN并行执行计算任务;

第2阶段reduce:返回局部的计算结果到汇总程序,汇总程序得出最终结果;

以上是对mapreduce计算思想的总结概括,那么hadoop中MapReduce程序执行过程如下:

map阶段:

1输入:当namenode将计算程序分发到各个节点时,datanode会将当前节点的数据按split块进行逻辑拆分,

(通常来说,一个split块大小与block块【物理划分】等同),每个inputSplit块执行一个计算任务,在JAVA程序中对应

mapper类.map()方法,具体计算由用户自定义【相应还有reducer类】,map()方法返回一个<k1,v1>键值对<所在位置,字符值>;

如 1.txt:

hello world

hello me

-> (RecordReader类会把每一个split解析成一各个<k1,v1>)

默认 一行数据就是一个<k1,v1>

<0,hello world> map任务1?从0开始

<12,hello me> map任务2?错,都在一个map任务中

2Mapper类.map()函数,<k2,v2> = map(<k1,v1>)

一个block 《对应》一个inputSplit 《对应》一个Map Task

对键值对根据值v1进行拆分(需要在map函数中自己实现):

<字符值,出现1次>

<k2,v2>

<hello,1>

<world,1>

<hello,1>

<me,1>

3对<k2,v2>进行分区,不同分区的<k2,v2>由不同的Reduce Task处理

默认只有一个分区(如果有多个分区,需要根据分区规则将数据分开)

根据k2对map对进行字符排序(案例中英文首字母)

<k2,v2>

<hello,1>

<hello,1>

<me,1>

<world,1>

4并合并成集合(把相同k2的v2放到一块):

<hello,{1,1}>

<me,{1}>

<world,{1}>

5可选操作 combiner,默认不执行,其实就是提前执行reduce聚合操作,

得到局部的聚合结果;

6将Map Task任务输出的<k2,v2>结果写入linux HDFS,持久化到磁盘空间中;

阶段总结:如果任务不需要聚合操作,执行完步骤2就可以将结果写入磁盘中;

reduce阶段:

有多少个分区,就有多少个reduce task ,就会输出多少个结果文件。

1将多个map task输出的结果根据分区 通过网络copy到不同分区的reduce task程序所在节点上–shuffle操作

分区1:

<k2,{v2…}>

<hello,{1,1}>

<me,{1}>

<world,{1}>

2框架对reduce节点上相同分区的<k2,{v2…}>进行合并、排序、分组

对map task中局部聚合过的结果进行全局聚合

3调用reducer类.reduce()方法把<k2,{v2…}> 聚合计算成 <k3,v3>

每个<k3,v3>都会调用一次reduce函数

<hello,2>

<me,1>

<world,1>

4格式化处理输出结果,使用制表符隔开:

hello 2

me 1

world 1

reduce阶段执行结束

分解步骤:mapreduce

mapTask:

1分片block-inputSplit-file 2读取每一行数据(记录偏移量和内容)<k1,v1> 3map()将数据内容切分形成<k2,v2>

4分区-对应一个reduce节点<k2,v2> 5分区内排序<k2,v2> 6分区内分组<k2,{v2…}> 7可选项:combiner 提前reduce

8结果存储到linux

reduceTask:

1Shuffle:将map结果集根据分区复制到对应分区的reduce节点上,如file1-block1-split1-maptask1-分区1、分区2

file2-block2-split2-maptask2-分区1、分区2

reduce时会将maptask1的分区1和maptask2的分区1计算的结果汇总到reduce分区1中进行最终计算;

分区2亦是如此。 2(排序):分区内汇总所有maptask上相应分区的结果并进行排序,

3分组:分区内分组; 4执行reduce聚合操作;

bug点1:
运行jar包时报 ClassNotFoundException异常,经排查发现是使用命令时必须指定使用类的具体路径:如
com.imooc.mr.WordCountJob

shuffle过程:指使用网络将数据从map端copy到reduce端的过程;
1分区分组排序阶段:当数据在内存中存储超过80mb时,会将多出的数据溢写到磁盘上(按分区存储),此时会产生数个小文件;
2合并阶段: 将一个map任务所有的小文件的合并成一个大文件,此文件也会分区;
shuffle会将此大文件按分区分发到对应分区的reduce节点上。

一个文件如果小于等于140M,那么只会产生一个map任务(一个文件inputSplit),而141M以上便会产生2个map任务;
因为源码中文件大小大于文件*1.1,才能产生新的split;

mapreduce小文件问题解决方案: hadoop集群处理大量的小文件是非常低效的,故将多个小文件合并成一个大文件成为了一种优化思路,
方法有sequenceFile 和 mapFile(排序后的sequenceFile,按什么排序),将小文件序列化成一个大文件,hadoop有封装好的类可以调用,但序列化文件需
要我们自己写程序转化出来!

数据倾斜问题描述:在执行MapReduce任务时,大部分reduce任务都很快执行完成,个别reduce任务很慢,可能卡在99%,故整个计算任务
耗时很长;
解决方法:找出导致倾斜的数据(出现次数多),将其打散。(hash?)
数据倾斜问题:
指的是当一个任务在用mapreduce进行处理的时候,若这份数据的某些值占比过高,就会造成某一个reduce任务需要处理的数据量远超其他reduce任务,而导致最终整体任务执行耗时偏长。
一般解决方案有两种:
1增加reduce任务的个数,新增一个reduce去同时执行耗时长的任务,看哪个执行的快,以快的为准,这种方法一般提升很小;
2将导致倾斜的数据打散,重新分配到每个reduce中,需要在数据值key中加入随机数来实现,但得到的结果还需进一步聚合才能得到最终结果。

map任务数由切片数决定,reduce任务数由分区数决定,而同一key会分发到同一个分区中,即按照输出数据不同的key分配到不同分区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值