MapReduce报错:java.io.IOException: Split metadata size exceeded 10000000

677 阅读3分钟

一、问题现象

客户在用hive sql做几张表的组合分析,使用mr引擎。 因为其中有一张表超过5万个分区,数据总量超过8千亿条,因此运行过程中出现失败,报错如下所示:

org.apache.hadoop.mapreduce.v2.app.job.impl.JobImpl:

Job init failed org.apache.hadoop.yarn.executions.YarnRuntimeException:

java.io.IOException:Split metadata size exceeded 10000000. Aborting job job_1558160008053_0002

根据报错,分析得到出错原因: 该job的job.splitmetainfo文件大小超过限制;

从hadoop源码里面可以查询到,是因为 mapreduce.job.split.metainfo.maxsize 参数默认设置1千万导致的。

为什么采用默认的1千万还不够呢?这就要从 mapreduce.job.split.metainfo.maxsize 参数的含义说起:

job.splitmetainfo该文件记录split的元数据信息,如input文件过多,记录的文件结构信息超出默认设置就会报错;输入文件包括大量小文件或者文件目录,造成Splitmetainfo文件超过默认上限。

这个机制也是hadoop集群要求文件大小不能过小或目录过多,避免namenode出现元数据加载处理瓶颈。如block默认128M,则文件应大于这个,尽量合并小文件。

那为什么这次hive sql会出错呢? 因为计算的hive表超过5万个分区,数据量超过8千亿,存储在HDFS上面的数据文件超过140万个,

mapreduce.job.split.metainfo.maxsize默认的10M大小不足以记录这些元数据。

二、修复方法

在mapred-site.xml配置文件中:

修改参数mapreduce.jobtracker.split.metainfo.maxsize =200000000(200M)

然后,重启mapreducev2、yarn组件;如果是hive sql任务,还需要重启hive。

当然,该问题的根本原因还是因为input小文件或者目录太多导致的,所以建议合并小文件。如果计算的hive表数据量确实太大,建议sql语句选择合适的分区,不要对整个表数据进行计算。

Hadoop平台作业参数设置关于mapreduce.job.split.metainfo.maxsize的说明

1、MR程序时执行时报错:

YarnRuntimeException: java.io.IOException:Split metadata size exceeded 10000000.

2、原因分析:

输入文件包括大量小文件或者文件目录,造成Splitmetainfo大小超过默认上限。

3、解决办法:

在mapred-site.xml配置文件中:

修改默认作业参数mapreduce.jobtracker.split.metainfo.maxsize =100000000

或者mapreduce.jobtracker.split.metainfo.maxsize = -1 (默认值是1000000)

mapreduce.job.split.metainfo.maxsize

10000000

4、深入分析:

job.splitmetainfo该文件记录split的元数据信息,如input文件过多,记录的文件结构信息超出默认设置就会报错;

这个机制也是Hadoop集群要求文件大小不能过小或目录过多,避免namenode出现元数据加载处理瓶颈,这种业务一般会出现在存储图片上。

如block默认128M,则文件应大于这个,尽量合并小文件。

5、源码分析:

org.apache.hadoop.mapreduce.split.JobSplit

可以看出splitmetainfo存储的文件结构信息内容:

    @Override
    public String toString() {
      StringBuffer buf = new StringBuffer();
      buf.append("data-size : " + inputDataLength + "\n");
      buf.append("start-offset : " + startOffset + "\n");
      buf.append("locations : " + "\n");
      for (String loc : locations) {
        buf.append("  " + loc + "\n");
      }
      return buf.toString();
    }

end