MR任务随机性运行失败

问题描述:
azkaban调度系统中有个别的几个flow总是随机性有任务失败,经查看日志发现如下错误
* java.io.FileNotFoundException: jenkins/mapred/local/1508958341829_tmp does not exist
* java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: Rename cannot overwrite non empty destination directory /tmp/hadoop-hadoop/mapred/local/1406915233073


问题原因:

    当多个线程运行MR程序时hadoop出现的问题:
         https://issues.apache.org/jira/browse/MAPREDUCE-6992
         https://issues.apache.org/jira/browse/MAPREDUCE-6441


解决背景:

        根据 When localizing distributed cache files in "local" mode, LocalDistributedCacheManager.java chooses a "unique" directory based on a millisecond time stamp. When running code with some parallelism, it's possible to run into this.

问题是org.apache.hadoop.mapred.LocalDistributedCacheManager类中的以下代码行:

    // Generating unique numbers for FSDownload.
    AtomicLong uniqueNumberGenerator =
       new AtomicLong(System.currentTimeMillis());

and

Long.toString(uniqueNumberGenerator.incrementAndGet())),

        hdfs会创建一个以当前时间的时间戳命名的文件.当两个mr任务在同一毫秒提交,造成了文件的并发访问问题.

yarn的运行模式:

1-本地模式(LocalJobRunner实现)
mapreduce.framework.name设置为local,则不会使用YARN集群来分配资源,在本地节点执行。在本地模式运行的任务,无法发挥集群的优势。注:在web UI是查看不到本地模式运行的任务。

        对 hive有些了解的人都会知道,hive 会将 SQL 语句最终转化成分布式执行的 mapreduce 任务计划。对于大数量集的数据启动 mapreduce 所花费的时间是渺小的。因为数据量大,并且分布再不同的机器上,在不同的机器上处理,这样做是 hive 的优势之一。然而当处理小数量,并且数据都聚集再一台机器上时,那么启动本地模式是非常有意的,不可避免的启动 mapreduce,将数据拉回客户端,本地处理,这样减少了分处理后合并花费的时间。如此一来,对数据量比较小的操作,就可以在本地执行,这样要比提交任务到集群执行效率要快很多。
启动本地模式,需要配置如下参数:     
     hive.exec.mode.local.auto                    决定 Hive 是否应该自动地根据输入文件大小,在本地运行。    
     hive.exec.mode.local.auto.inputbytes.max     最大输入数据量,当输入数据量小于这个值的时候将会启动本地模式,默认是 128M。    
     hive.exec.mode.local.auto.tasks.max          最大输入文件个数,当输入文件个数小于这个值的时候将会启动本地模式。(默认4)

当一个job满足如下条件才能真正使用本地模式:      

  1.job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB)    
  2.job的map数必须小于参数:hive.exec.mode.local.auto.tasks.max(默认4)    

  3.job的reduce数必须为0或者1


2-Yarn模式(YARNRunner实现)
        mapreduce.framework.name设置为yarn,当客户端配置mapreduce.framework.name为yarn时, 客户端会使用YARNRunner与服务端通信, 而YARNRunner真正的实现是通过ClientRMProtocol与RM交互, 包括提交Application, 查询状态等功能。但是根据任务的特性,分为两种方式执行任务


3-Uber模式:

        为降低小作业延迟而设计的一种模式,所有任务,不管是Map Task,还是Reduce Task,均在同一个Container中顺序执行,这个Container其实也是MRAppMaster所在Container

4-Non-Uber模式:

         对于运行时间较长的大作业,先为Map Task申请资源,当Map Task运行完成数目达到一定比例后再为Reduce Task申请资源。


解决办法:

1-在不改源代码的情况下,取消自动启动本地模式,根据集群环境,临时在运行程序时设置:
set hive.exec.mode.local.auto = false

2-在调度系统中设置设置失败重试.

azkaban配置失败重试如下:
type =command
command = xxxxxx
retries=3
retry.backoff=60000 #毫秒数

3-根据网上给的建议,将以时间戳命名的方式的代码改成使用uuid.


猜你喜欢

转载自blog.csdn.net/weixin_39445556/article/details/80348976