在执行Reduce Shuffle的过程中,偶尔会遇到Shuffle Error,但是重启任务之后,Shuffle Error会消失,当然这只是在某些特定情况下才会报出来的错误。虽然在每次执行很短的时间报出这个错误,但是如果单个Reducer的错误数量超出maxAttempt,就会导致整个任务失败。

Error: org.apache.hadoop.mapreduce.task.reduce.Shuffle$ShuffleError: error in shuffle in fetcher#50
at org.apache.hadoop.mapreduce.task.reduce.Shuffle.run(Shuffle.java:121)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:380)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:162)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1491)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:157)
Caused by: java.lang.OutOfMemoryError: Java heap space
at org.apache.hadoop.io.BoundedByteArrayOutputStream.<init>(BoundedByteArrayOutputStream.java:56)
at org.apache.hadoop.io.BoundedByteArrayOutputStream.<init>(BoundedByteArrayOutputStream.java:46)
at org.apache.hadoop.mapreduce.task.reduce.InMemoryMapOutput.<init>(InMemoryMapOutput.java:63)
at org.apache.hadoop.mapreduce.task.reduce.MergeManagerImpl.unconditionalReserve(MergeManagerImpl.java:297)
at org.apache.hadoop.mapreduce.task.reduce.MergeManagerImpl.reserve(MergeManagerImpl.java:287)
at org.apache.hadoop.mapreduce.task.reduce.Fetcher.copyMapOutput(Fetcher.java:411)
at org.apache.hadoop.mapreduce.task.reduce.Fetcher.copyFromHost(Fetcher.java:341)
at org.apache.hadoop.mapreduce.task.reduce.Fetcher.run(Fetcher.java:165)

本分析过程同时借鉴了这篇blog:

http://www.sqlparty.com/yarn%E5%9C%A8shuffle%E9%98%B6%E6%AE%B5%E5%86%85%E5%AD%98%E4%B8%8D%E8%B6%B3%E9%97%AE%E9%A2%98error-in-shuffle-in-fetcher/

结合hadoop 2.2.0的源代码来对整个失败过程进行简要分析。

从代码分析来看,最底层Fetcher.run方法执行时出现的错误,在Shuffle.run方法中,会启动一定数量的Fetcher线程(数量由参数mapreduce.reduce.shuffle.parallelcopies决定,我们配置的事50个,是不是有点多,默认是5),Fetcher线程用来从map端copy数据到Reducer端本地。

Fetcher<K,V>[] fetchers = new Fetcher[numFetchers];
for (int i=0; i < numFetchers; ++i) {
fetchers[i] = new Fetcher<K,V>(jobConf, reduceId, scheduler, merger,
reporter, metrics, this,
reduceTask.getShuffleSecret());
fetchers[i].start();
} // Wait for shuffle to complete successfully
while (!scheduler.waitUntilDone(PROGRESS_FREQUENCY)) {
reporter.progress(); synchronized (this) {
if (throwable != null) {
throw new ShuffleError("error in shuffle in " + throwingThreadName,
throwable);
}
}
}

当任意一个Fetcher发生异常时,就会在scheduler的等待后能够在主线程发现,停掉整个Reducer。

public synchronized void reportException(Throwable t) {
if (throwable == null) {
throwable = t;
throwingThreadName = Thread.currentThread().getName();
// Notify the scheduler so that the reporting thread finds the
// exception immediately.
synchronized (scheduler) {
scheduler.notifyAll();
}
}
}

在异常堆栈发生的地方,Fetcher中调用copyFromHost方法,调用到Fetcher的114行,merger.reserve方法会调用MergerManagerImpl.reserve

@Override
public synchronized MapOutput<K,V> reserve(TaskAttemptID mapId,
long requestedSize,
int fetcher
) throws IOException {
if (!canShuffleToMemory(requestedSize)) {
LOG.info(mapId + ": Shuffling to disk since " + requestedSize +
" is greater than maxSingleShuffleLimit (" +
maxSingleShuffleLimit + ")");
return new OnDiskMapOutput<K,V>(mapId, reduceId, this, requestedSize,
jobConf, mapOutputFile, fetcher, true);
}
...

重点是这个canShuffleToMemory方法,它会决定是启动OnDiskMapOutput还是InMemoryMapOutput类,标准就是需要的内存数量小于设置的限制。

private boolean canShuffleToMemory(long requestedSize) {
return (requestedSize < maxSingleShuffleLimit);
}

在初始化MergerManageImpl的时候设置了这个限制,MRJobConfig.REDUCE_MEMORY_TOTAL_BYTES(mapreduce.reduce.memory.totalbytes)这个参数我们并没有设置,因此使用的是Runtime.getRuntime.maxMemory()*maxInMemCopyUse, MRJobConfig.SHUFFLE_INPUT_BUFFER_PERCENT(mapreduce.reduce.shuffle.input.buffer.percent) 参数使用的是0.70,也就是最大内存的70%用于做Shuffle/Merge,比如当前Reducer端内存设置成2G,那么就会有1.4G内存。

final float maxInMemCopyUse =
jobConf.getFloat(MRJobConfig.SHUFFLE_INPUT_BUFFER_PERCENT, 0.90f);
this.memoryLimit =
(long)(jobConf.getLong(MRJobConfig.REDUCE_MEMORY_TOTAL_BYTES,
Math.min(Runtime.getRuntime().maxMemory(), Integer.MAX_VALUE))
* maxInMemCopyUse);
final float singleShuffleMemoryLimitPercent =
jobConf.getFloat(MRJobConfig.SHUFFLE_MEMORY_LIMIT_PERCENT,
DEFAULT_SHUFFLE_MEMORY_LIMIT_PERCENT);
this.maxSingleShuffleLimit =
(long)(memoryLimit * singleShuffleMemoryLimitPercent);

而单个Shuffle最大能够使用多少内存,还需要再乘一个参数:MRJobConfig.SHUFFLE_MEMORY_LIMIT_PERCENT(mapreduce.reduce.shuffle.memory.limit.percent),我们当前并没有设置这个参数,那么默认值为0.25f,此时单个Shuffle最大能够使用1.4G*0.25f=350M内存。

InMemory会在初始化时接收一个size参数,这个size的计算方式暂时未知,用于初始化其BoundedByteArrayOutputStream,

public InMemoryMapOutput(Configuration conf, TaskAttemptID mapId,
MergeManagerImpl<K, V> merger,
int size, CompressionCodec codec,
boolean primaryMapOutput) {

这个size也就是BoundedByteArrayOutputStream作为byte[]的大小:

public BoundedByteArrayOutputStream(int capacity, int limit) {
this(new byte[capacity], 0, limit);
}

OOM也就是出现在这一行。

而我们出的错可能就是出现在判定为使用InMemoryMapOutput但是分配内存时出现的错误,试想使用50个Fetcher线程,单个线程设置为最大接收350M,而堆的最大内存为2G,这样只要有7个Fetcher线程判断为使用InMemoryMapOutput,且同时开始接收数据,就可能造成Java Heap的OOM错误,从而导致Shuffle Error。

我觉得我们可以对使用的参数进行一定的调整,比如说减少Fetcher线程的数量,减少单个Shuffle使用InMemory操作的比例让其OnDisk操作等等,来避免这个问题。

hadoop Shuffle Error OOM错误分析和解决的更多相关文章

  1. MySQL常见错误分析与解决方法总结

    MySQL常见错误分析与解决方法总结 一.Can't connect to MySQL server on 'localhost' (10061)翻译:不能连接到 localhost 上的mysql分 ...

  2. Hadoop org.apache.hadoop.util.DiskChecker$DiskErrorException问题等价解决linux磁盘不足解决问题排查

    org.apache.hadoop.util.DiskChecker$DiskErrorException问题等价解决linux磁盘不足解决问题排查 解决"/dev/mapper/cento ...

  3. vss error reading from file 解决方法

    vss error reading from file 解决方法 1 若服务器中存在 vss/data/backup目录,请将该目录删掉2 运行cmd cd.. cd C:\Program Files ...

  4. Error reading from file 解决办法

    最近安装程序遇见这个问题: Error reading from file. 解决办法: 给这个程序添加权限: 添加SYSTEM的读写改..如果比较懒,直接全部允许. 然后Retry.

  5. hadoop Safe mode is ON 的解决办法

    hadoop Safe mode is ON 的解决办法 搭了一个hadoop集群环境,近期总是出现读写文件错误的情况,查看name node的日志显示 (Safe mode is ON) Safe ...

  6. Hadoop build error java.lang.NoClassDefFoundError: org/sonatype/aether/graph/DependencyFilter

    When running the command: + mvn site site:stage -DskipTests -DskipTest -DskipITs   you get an error: ...

  7. 安装CAD出现Error 1904.Module的解决方法

    在安装AutoCAD2008时,安装过程中出现了一个小错误,虽然说不影响使用,也不影响功能,但还是需要把这个问题解决,今天就和大家分享解决这个问题的方法. 错误描述 会在安装过程中出现错误提示:Err ...

  8. Android studio Error: Modules no specified解决和真机调试

    如何配置SDK百度一大堆: 前言:Android Studio很完善,如果SDK配置好,理论上就是 创建项目->创建个APP(名字自己随便起)->打开手机开发者模式运行即可:如果出了问题, ...

  9. 关于163发邮件报错535 Error:authentication failed解决方法

    关于发邮件报错535 Error:authentication failed解决方法 调用163邮箱服务器来发送邮件,我们需要开启POP3/SMTP服务,这时163邮件会让我们设置客户端授权码,这个授 ...

随机推荐

  1. C与C++基础知识补遗

    本随笔用来记载项目开发中遇到的以前没掌握的C/C++基础知识 void * buffer; 无类型指针,可以指向任何类型数据.ANSI标准规定无类型指针不能进行算法,而GNU规定无类型指针算法操作与c ...

  2. office在繁体系统下 导入导出 功能灰显的解决方法

    当在win7系统使用繁体中文版的office时,或系统是繁体版时,可能会导致office的导入导出功能无法使用 解决方法: 控制面板--区域和语言--格式--中文简体

  3. Oracle解决中文乱码

    原因 经过一番查证,发现问题的源头不是出现在PLSQL上,而是出现在我们的Oracle上,由于我们的Oracle数据库里的字符集不支持中文导致的,既然知道了原因,就好办了,我们就配置我们的Oracle ...

  4. MB到片组的映射

    待分析 链接原文: http://blog.csdn.net/mr_phy/article/details/61638262

  5. MySQL在本机无法基于localhost访问的问题解决

    引言: 在本地访问数据库之时,一般使用localhost, 127.0.0.1来进行数据库访问,但是笔者这几天就碰到了只能通过127.0.0.1来访问,但是无法基于localhost来访问,非常之诡异 ...

  6. 将海康大华等网络摄像机RTSP流进行网页Flash rtmp和H5 hls直播的技术方案

    前言 再小的技术点也会有他的市场! 一直以来,都有一些不被看好,认为是成本太高,无法大规模展开的软件和产品形态,就好比每一座城市都会有他的著名小吃一样,即使是慕名而来的人源源不断,受众群体也总是有限, ...

  7. XOR Queries(莫队+trie)

    题目链接: XOR Queries 给出一个长度为nn的数组CC,回答mm个形式为(L, R, A, B)(L,R,A,B)的询问,含义为存在多少个不同的数组下标k \in [L, R]k∈[L,R] ...

  8. PHP中cookies跨目录无法调用

    <?php  setcookie("messagetime",time(),time()+60);  ?> 写法无法跨目录调用呢.在搜索引擎中搜索,并没有找到答案(可能 ...

  9. SQL基础五(作业代码)

    create database stuinfo create table student ( mid ) not null primary key, mname ) not null ) create ...

  10. python类中self是什么

    参考文献:http://www.cnblogs.com/linuxcat/archive/2012/01/05/2220997.html 注: (1)self在定义类的方法时是必须有的. (2)调用时 ...