MapReduce(笔记八)

本文详细解析了MapReduce的执行过程,包括Map阶段的读取、处理和写入,以及Reduce阶段的Copy、Merge和Reducer的输入文件。shuffle阶段包括collect、spill、merge和copy等步骤。数据倾斜表现为部分task执行缓慢或导致OOM,解决方案包括增加内存、调整reduce个数、自定义分区和使用Combiner。同时,文章还探讨了内存溢出的原因和类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MapReduce 执行过程分析

Mapreduce-分布式运算框架,用户开发“基于hadoop的数据分析应用”的核心框架

Map

1.数据

mapTask读取数据源文件进行切片,每一个block启动一个mapTask,每个map task按照行读取一个block中的内容

2.处理数据

map函数对输入的每一行数据进行处理

在内存中将数据存到环形缓冲区(byte[]数组),进行sort排序,自定义分区(每个分区对应一个reduceTask,缓解数据倾斜问题,可以让后面的reduce平均分摊任务,默认对key hash后再以reduce task数量取模),让结构变得简单

3.写入数据到磁盘

缓冲区达到80%默认大小100M超过则溢写磁盘临时文件)在map端执行spill,输出<word,次数>(尽可能一次性合并多个spill)按照key进行分组排序( 有combiner就combiner降低网络数据传输时 间,让后面的reduce阶段,平均分摊任务),归并后可以进行压缩操作(对CPU造成压力,对IO有利)

Reduce

1.copy:拉取数据,获取map task的在磁盘里面的输出文件(添加并发下载的线程数)

2.Merge:这里的merge如map端的merge动作,只是数组中存放的是map端copy来的数值,Copy过来的数据会先放入内存缓冲区中,这里的缓冲区大小要比map端的更为灵活,它基于JVM的heap size设置

merge有三种形式:1)内存到内存 2)内存到磁盘(默认) 3)磁盘到磁盘。默认情况下第一种 形式不启用。当内存中的数据量到达一定阈值,就启动内存到磁盘的merge。与map 端类似,这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。第二种merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的那个文件。

3.Reducer的输入文件。不断地merge后,最后会生成一个“最终文件”。默认情况下,这个文件是存放于磁盘中的。

环形缓冲区
1.为什么要环形缓冲区?
答:使用环形缓冲区,便于**写入**缓冲区和**写出**缓冲区**同时进行**,批量收集map结果,减少磁盘IO的影响
2.为什么不等缓冲区满了再spill?
答:**会出现阻塞。**
3.数据的分区和排序是在哪完成的?
答:分区是根据**元数据**meta中的**分区号**partition来分区的,**排序是在spill**的时候排序。

4.Shuffle 中的缓冲区大小会影响到 mapreduce 程序的执行效率,原则上说,缓冲区越大,磁盘 io 的次数越少,执行速度就越快

shuffle阶段做了什么?什么是shuffle阶段?

map输出到reduce输入的中间过程就是shuffle阶段

(1)collect阶段:将 MapTask 的结果输出到默认大小为 100M 的环形缓冲区,

保存的是 key/value,Partition 分区信息等。

(2)spill阶段:当内存中的数据量达到一定的阀值的时候,就会将数据写

入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置

了 combiner,还会将有相同分区号和 key 的数据进行排序。

(3)merge阶段:把所有溢出的临时文件进行一次合并操作,以确保一个

MapTask 最终只产生一个中间数据文件

(4)copy阶段:ReduceTask中Fetcher 线程到已经完成 MapTask 的节点

上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区

(5)merge阶段:当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上。在 ReduceTask 远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。

(6)sort阶段:在对数据进行合并的同时,会进行排序操作,由于 MapTask

阶段已经对数据进行了局部的排序,ReduceTask 只需保证 Copy 的数据的最终整

体有效性即可。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

请添加图片描述

Mapreduce数据倾斜原因和解决方案

数据倾斜:

简单来说数据倾斜就是
大量的相同key被partition分配到一个分区里
造成一部分数据很多,一部分数据很少的局面。

数据倾斜发生时的现象:

1、绝大多数task执行得都非常快,但个别task执行的极慢
2、原本能正常执行的Spark作业,某天突然爆出OOM(内存溢出)异常。观察异常栈,是我们写的业务代码造成的

HiveSQL语句中的发生数据倾斜的状况

1.group by 维度过小,某值的数量过多,导致处理某值的reduce非常耗时,

2.特殊值过多,解决:去重操作distinct

3.其中一个表较小,但是key集中,分发到某一个或几个Reduce上的数据远高于平均值

4.分桶的判断字段0值或空值过多

5.没有把重复关联键少的表放在join前面,写在关联左侧的表每有1条重复的关联键时底层就会多1次运算处理

解决方案

1、增加jvm内存,通过硬件的手段来进行调优,显著的提高运行效率

2、增加reduce的个数,计算的节点多了,就算工作量还是不均匀的,那也要小很多

3、自定义分区,指定分区策略

5、使用combinner合并,大量的相同key数据先进行一个合并(local reduce),减轻了map端向reduce端发送的数据量(减轻了网络带宽),也减轻了map端和reduce端中间的shuffle阶段的数据拉取数量(本地化磁盘IO速率),推荐使用这种方法。

oom

一.为什么会OOM

主要是以下两点:

1、  分配的内存少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少

2、 应用程序太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出

内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出申请的内存超出了JVM能提供的内存大小,此时称之为溢出。

二.OOM的类型有哪些

Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。

Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。

Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。

**1、*java.lang.OutOfMemoryError: Java heap space*java

堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms(初始堆大小),-Xmx(最大堆大小)等修改。

2、java.lang.StackOverflowError,不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数**-Xss(栈大小)**来设置栈的大小。

public class StackOverflowErrorDemo {
public static void main(String[] args) {
    javaKeeper();
}

private static void javaKeeper() {
    javaKeeper();
}
}
//JVM 虚拟机栈是有深度的,在执行方法的时候会伴随着入栈和出栈,上边的方法可以看到,main 方法执行后不停的递归,迟早把栈撑爆了

3.GC overhead limit exceeded

JVM 内置了垃圾回收机制GC,所以作为 Javaer 的我们不需要手工编写代码来进行内存分配和释放,但是当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded 错误(俗称:垃圾回收错误,GC开销超过限制)。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。

假如不抛出 GC overhead limit exceeded 错误,那 GC 清理的那么一丢丢内存很快就会被再次填满,迫使 GC 再次执行,这样恶性循环,CPU 使用率 100%,而 GC 没什么效果。

3.1 写个 bug
出现这个错误的实例,其实我们写个无限循环,往 List 或 Map 加数据就会一直 Full GC,直到扛不住,这里用一个不容易发现的栗子。我们往 map 中添加 1000 个元素。

检查项目中是否有大量的死循环或有使用大内存的代码优化代码
dump内存分析检查是否存在内存泄露如果没有加大内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值