本文为您介绍在使用MapReduce时的常见问题。

问题类别 常见问题
功能咨询
开发MapReduce
常见报错

MapReduce的输入源可以是视图吗?

不可以,只能是表。

MapReduce的结果写入到表或分区时,会覆盖还是追加数据?

会覆盖掉原有的表数据或分区数据。

MapReduce中是否可以调用Shell文件?

不可以,受Java沙箱限制。更多Java沙箱信息,请参见 Java沙箱

reduce.setup能否读入输入表?

不能读入输入表,只能读入缓存表。

Mapper是否支持同一表格多分区输入?

Mapper支持同一表格多分区输入,同一张表的多个分区可以理解为独立的两张表。

Mapper可以直接从Record中读取分区数据段的信息吗?

Mapper无法从Record中获取分区字段信息,但是可以使用如下代码。PartitionSpec为分区信息。
PartitionSpec ps = context.getInputTableInfo().getPartitionSpec();
String area = ps.get(“area”);        

Label和分区是什么关系?

Label是给不同的输出处打上的一个标签,当输出的时候可以识别是从哪里输出的。

MapReduce中是否可以只有Map?

可以,MapReduce支持Map-Only。如果是Map-Only作业,需要显式指定Reducer数量为0,即 job.setNumReduceTasks(0)

Mapper中输入表中的每条Record数据,是否可以按列名读取?

可以。输入表中的每条Record数据不仅可以按序号 record.get(i) 读取,还可以按照列名来获取Record,例如 record.get("size")

write(Record key, Record value) write(Record record) 的区别是什么?

  • write(Record key, Record value) :输出中间结果,例如 key.set(“id”, v1),value.set(“size”, v2) 。Map产出的中间结果,需要网络传输给Reduce,没有关联表进行类型推断,所以必须声明字段类型用于序列化。输出的字段类型是MaxCompute的字段类型。
    job.setMapOutputKeySchema(SchemaUtils.fromString(“id:string”));  
    job.setMapOutputValueSchema(SchemaUtils.fromString(“size:bigint”));               
  • write(Record record) :输出结果到最终表,有表进行类型推断,没必要声明字段类型。

MaxCompute MapReduce中,为什么要指定两个JAR,Libjars和Classpath?

本地客户端会执行一些作业配置等操作,涉及远程执行。因此本地有一个执行器,远程有一个执行器。

远程执行器执行加载远程的Classpath,即 -libjars mapreduce-examples.jar 。本地执行器加载本地Classpath,所以也要指定 -classpath lib/mapreduce-examples.jar

Hadoop MapReduce的源码,能否直接应用于MaxCompute MapReduce?

不能。MaxCompute MapReduce与Hadoop MapReduce API有一定差别,但整体风格一致。您需要修改Hadoop的源码,并在MaxCompute MapReduce SDK下编译通过后,才能在MaxCompute上运行。

MapReduce如何实现排序?

排序代码如下。
//设置排序的字段(这里根据i1,i2两个字段进行排序)。
job.setOutputKeySortColumns(new String[] { "i1", "i2" });
//设置字段的排序顺序(这里设置i1为正序排序,i2为逆序排序)。
job.setOutputKeySortOrder(new SortOrder[] { SortOrder.ASC, SortOrder.DESC });        
setOutputKeySortOrder方法的用法,如下所示。
public void setOutputKeySortOrder(JobConf.SortOrder[] order)
功能:设置Key排序列的顺序。
参数: Order表示排序列的顺序。可选值为ASC(升序)、DESC(降序)。       

MapReduce中的Backups是什么?

Backups就是一种加速调优。MaxCompute会查看您的任务,如果存在一些任务的工作量特别大,便为其开启备份任务,两个任务执行一样的数据,结果用最先执行结束的任务,因此存在Backups。但是如果任务非常大,Backups也无法起作用,因为原本的任务和Backups都没有执行完成。

开发MapReduce时,如何在命令行传入多个资源?

用逗号(,)分隔符进行分隔,例如输入命令 jar -resource resource1,resource2,.. 即可。

在Main方法中如何判断一个表为空表?

您可以使用如下方式判断一个表是否为空表。
Odps odps=SessionState.get().getOdps();
Table table=odps.tables().get('tableName');
RecordReader recordReader=table.read(1);
if(recordReader.read()==null){
//TO DO      

在MaxCompute MapReduce中,如何设置Java代码,才能打印出日志?

推荐如下方法:
  • 可以在代码中用 System.out.println 打印日志,对应日志输出位置是在Logview的stdout中。
  • 使用出现异常时,客户端会返回异常信息,不需要打印日志信息。
  • 使用common logging,日志输出到stderr中,可以在Logview的stderr看到。

结果表中会保留两个MapReduce计算之后的重复数据吗?

会。查询数据时,会得到两条一样的数据。

Hadoop中可以选择多个Node进行分布处理(一个Node表示一台机器),那么MaxCompute MapReduce进行分布处理时,该如何设置Node?

您不需要自行搭建分配Node,这正是MaxCompute的优点之一。

当运行MapReduce时,MaxCompute底层会根据算法决定使用的数据分片。

不使用Combiner时输出正常,使用Combiner后Reduce没有输入,是什么原因?

Reduce输出的单个Record和Map输出的Key-Value对不一致,导致产生上述情况。

在MapOnly中,为什么程序没有指定输出Table的Schema格式?

输出表的Schema是需要预先创建好的,在 create table 的时候指定。MapOnly程序内部不用指定Schema,可以直接输出。

如何在本地调用MaxCompute服务器运行MapReduce任务?

正常情况下,MaxCompute的JAR包需要在命令行工具上执行 jar 命令来执行,具体语法请参见 MapReduce作业提交

您也可以通过模拟的方式整合到自己的工程中,方法如下:
  1. 设置包依赖。

    除了基本的SDK,还需要其他的几个依赖包,您可在客户端工具的lib文件夹中找到。lib文件夹中也包含了SDK的JAR包,建议您在导入包的时候把最新的客户端工具lib文件夹中的JAR包全部导进来。

  2. 上传JAR包。

    将在本地测试通过的MapReduce程序,打成JAR包并上传,假设此JAR包的名称是 mr.jar 。更多上传资源操作,请参见 资源操作

  3. 设置运行方式。
    配置Jobconf,配置示例如下。
    //配置MaxCompute连接信息。
    Account account = new AliyunAccount(accessid, accesskey);
    Odps odps = new Odps(account);
    odps.setEndpoint(endpoint);
    odps.setDefaultProject(project);
    //获取session。
    SessionState ss = SessionState.get();
    ss.setOdps(odps);
    ss.setLocalRun(false);  //设置false,表示在服务器上跑。如果要在本地调试,直接设置为true。
    //正常的设置jobconf等代码。
    Job job = new Job();
    String resource = “mr.jar”;
    job.setResources(resource); //这一步类似Jar命令的jar -resources mr.jar。
    //后面的代码为正常的MapReduce代码规则。
    job.setMapperClass(XXXMapper.class);
    job.setReducerClass(XXXReducer.class);                            

    配置完成之后,您可以直接运行MapReduce任务。

执行MaxCompute MapReduce时,报错BufferOverflowException,如何解决?

  • 问题现象

    执行MaxCompute MapReduce时,返回如下报错。

    FAILED: ODPS-0123131:User defined function exception - Traceback:
         java.nio.BufferOverflowException
         at java.nio.DirectByteBuffer.put(Unknown Source)
         at com.aliyun.odps.udf.impl.batch.TextBinary.put(TextBinary.java:35)   
  • 产生原因

    一次写入的数据太大,导致Buffer溢出。

  • 解决措施

    MaxCompute的单个字段可以写入的数据类型限制如下。

    String      8MB
    Bigint      -9223372036854775807 ~ 9223372036854775807
    Boolean     True/False
    Double      -1.0 10308 ~ 1.0 10308
    Date        0001-01-01 00:00:00 ~ 9999-12-31 23:59:59                  

执行MaxCompute MapReduce时,报错Resource not found,如何解决?

提交作业时,要用 -resources 指定需要的资源,多个资源用逗号(,)分隔。

执行MaxCompute MapReduce时,报错Class Not Found,如何解决?

执行MapReduce时,以下两种情况会报此错误:
  • classpath 参数的类名写错,要写上完整的包名。
  • 打包JAR的时候出错,注意打包时要把SRC中的源码都选上。

执行MaxCompute MapReduce时,报错ODPS-0010000,如何解决?

  • 问题现象:

    执行MaxCompute MapReduce时,返回如下报错。

    ODPS-0010000: System internal error - get input pangu dir meta fail.
  • 产生原因

    出现上述报错,是因为您还未创建分区,或是因为分区数据未到位,您就开始使用此分区。

  • 解决措施

    先创建分区,然后再运行MapReduce任务。

执行MaxCompute MapReduce时,报错Table not found,如何解决?

  • 问题现象:

    执行MaxCompute MapReduce时,返回报错如下。

    Exception in thread "main" com.aliyun.odps.OdpsException: Table not found: project_name.table_name.
  • 产生原因

    目标项目不正确或目标表不存在。

  • 解决措施

    MapReduce接口的Table Info Builder是ProjectName和TableName,两个接口分别设置为Project名称和Table名称。

执行MaxCompute MapReduce时,报错ODPS-0123144,如何解决?

  • 问题现象:

    执行MaxCompute MapReduce时,返回报错如下。

    FAILED: ODPS-0123144: Fuxi job failed - WorkerRestar
  • 产生原因:

    出现上述报错,是因为集群的备节点在计算的过程中出现超时的情况,导致主节点认为备节点故障,所以报错。超时10分钟,即会报错,暂时不支持用户自行配置。

  • 解决措施

    这个报错比较常见的原因是Reduce里做了大循环,例如存在长尾数据或者笛卡尔积。您需要尽量减少这种大循环的情况。

执行MaxCompute MapReduce时,报错java.security.AccessControlException,如何解决?

  • 问题现象

    执行MaxCompute MapReduce时,返回报错如下。

    FAILED: ODPS-0123131:User defined function exception - Traceback:
    java.lang.ExceptionInInitializerError
    Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getProtectionDomain")
      at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)       
  • 产生原因

    出现上述报错,是因为您的代码违反了沙箱限制,详情请参见 Java沙箱

  • 解决措施

    您需要访问外部的资源解决此报错。但MaxCompute目前不支持访问外部资源,请将外部的处理逻辑和涉及的数据存储在MaxCompute上进行访问。您需要读取一些配置文件,详情请参见 使用资源示例

执行MaxCompute MapReduce时,报错 java.io.IOException,如何解决?

  • 问题现象:

    执行MaxCompute MapReduce时,返回报错如下。

    Exception in thread “main“ java.io.IOException: ODPS-0740001: Too many local-run maps: 101, must be <= 100(specified by local-run parameter ‘odps.mapred.local.map.max.tasks‘)     
  • 产生原因

    local-run maps 默认是100,需要调整。

  • 解决措施

    您可以添加 -Dodps.mapred.local.map.max.tasks=200 配置。

执行MaxCompute MapReduce时,报错Exceed maximum read times,如何解决?

  • 问题现象:

    执行MaxCompute MapReduce时,返回报错如下。

    ODPS-0730001: Exceed maximum read times per resource       
  • 产生原因:

    资源文件读取的次数太多。

  • 解决措施

    请检查代码中读取对应资源的代码逻辑。一般情况下,资源读取在setup中执行一次即可,不要在Map或Reduce阶段中多次读取。

执行MaxCompute MapReduce时,Reduce还没开始执行第一句,便报错为内存溢出,如何解决?

  • 产生原因

    某些数据特别大,下载到内存便溢出了。

  • 解决措施

    把Combiner去掉或者在Combiner中限制Size set odps.mapred.map.min.split.size=512;

执行MaxCompute MapReduce时,报错内存溢出,如何解决?

内存溢出通常是由于内存不足导致的,可以通过调整JVM内存参数( odps.stage.mapper.jvm.mem和odps.stage.reducer.jvm.mem )解决。例如 set odps.stage.mapper.jvm.mem = 2048 将内存调整为2 GB。

执行MaxCompute MapReduce时,开启了600个Reducer加载一个配置文件,但是配置文件很小且报错java.lang.OutOfMemoryError,如何解决?

  • 问题现象

    执行MaxCompute MapReduce时,返回报错如下。

    java.lang.OutOfMemoryError: Java heap space
  • 产生原因

    MapReduce使用限制导致,请参见 使用限制

  • 解决措施

    请参见 原生SDK概述 进行配置。

执行MaxCompute MapReduce时,报错ODPS-0420095,如何解决?

  • 问题现象

    执行MaxCompute MapReduce时,返回报错如下。

    Exception in thread "main" java.io.IOException: com.aliyun.odps.OdpsException: ODPS-0420095: Access Denied - The task is not in release range: LOT
  • 产生原因

    项目为MaxCompute开发者版资源下的项目,仅支持MaxCompute SQL(支持使用UDF)、PyODPS作业任务,暂不支持MapReduce、Spark等其它任务。

  • 解决措施

    升级项目规格,请参见 转换计费方式

在MapReduce中使用资源时,报错文件太多,如何解决?

  • 问题现象

    在MapReduce中使用资源时,返回报错如下。

     Caused by: com.aliyun.odps.OdpsException: java.io.FileNotFoundException: temp/mr_XXXXXX/resource/meta.user.group.config (Too many open files)
  • 产生原因

    单个作业引用的资源数量不能超过256个,否则报错。Table和Archive按照一个单位计算。更多限制请参见 使用限制

  • 解决措施

    调整引用的资源数量。

在MapReduce程序中使用第三方类,打了一个Assembly的JAR包,运行时报错找不到类,如何解决?

MaxCompute MapReduce在分布式环境中运行时受到Java沙箱的限制(MapReduce作业的主程序则不受此限制),具体限制请参见 Java沙箱

如果您只是需要处理Json,建议您直接使用Gson,同时无需打包带Gson的Class。Java开源组件里提供了很多字符串转日期的方法,例如SimpleDateFormat等。

使用开源兼容MapReduce在MaxCompute上运行时,报错显示下标越界,如何解决?

建议您使用MaxCompue的MapReduce接口进行代码编写。同时,非必须场景下建议使用Spark替代MapReduce。