hive任务卡在个别reduce的问题分析,hive任务reduce


        最近微博有一个任务需要使用日曝光表做统计,发现这个任务很容易在stage1卡在reduce100%阶段不动,发邮件过来让帮找一下问题或者优化一下,和同事一起分析了一下原因,以下是分析过程:

1、分析hql

add file get_recept_mid.sh;
add file get_last_expo_mid.sh;
add file get_real_recept.py;
insert overwrite directory '/user/liangjun/hive-liangjun/' 
select transform(t2.uid,t7.mid,t2.expo_mid) using 'python get_real_recept.py' as uid,real_recept 
from ( 
    select transform(t6.*) using 'sh get_recept_mid.sh' as uid,mid 
    from ( select t3.fans_uid,t4.mid from ( select fans_uid,uid from mds_user_fanslist where    dt=20140926 ) t3 join ( 
    select transform(t5.*) using 'sh get_recept_mid.sh' as uid,mid 
   from ( select uid,mid from mds_bhv_pubblog where dt=20140926 distribute by uid sort by uid ) t5   
    ) t4 on t3.uid=t4.uid distribute by t3.fans_uid sort by t3.fans_uid ) t6 ) t7 join	( 
    select transform(t1.*) using 'sh get_recept_mid.sh' as uid,expo_mid 
    from ( select t8.* from ( 
    select transform(ods_tblog_expo.uid,ods_tblog_expo.mid_list) 
             using 'sh get_last_expo_mid.sh' as uid,mid 
    from ods_tblog_expo where dt=20140926 and interface_id in ('1','5') ) t8 distribute by t8.uid sort  
    by t8.uid ) t1 ) t2 on t7.uid=t2.uid;

该hql有个特点:使用了多个脚本,包括python、shell

2、看是否有报错信息:

没有发现报错,但是卡在selectoperator处:

2014-09-29 10:22:23,162 INFO ExecReducer: ExecReducer: processing 10000000 rows: used memory = 110701640
2014-09-29 10:22:23,162 INFO org.apache.hadoop.hive.ql.exec.ExtractOperator: 2 forwarding 10000000 rows
2014-09-29 10:22:23,162 INFO org.apache.hadoop.hive.ql.exec.SelectOperator: 3 forwarding 10000000 rows

3、看是否有数据倾斜问题

查看了已经运行完成的reduce和卡住的reduce的counter信息,几个重要指标(FILE_BYTES_READFILE_BYTES_WRITTEN、HDFS_BYTES_WRITTEN)都差不多,不存在数据倾斜问题,但是FILE_BYTES_READ一直在动,而HDFS_BYTES_WRITTEN一直没反应。

4、查看了一下卡住的reduce任务java进程使用内存和cpu的情况

根据50030监控页面,找到卡住reduce任务运行所在的节点,根据任务id找到对应的进程id,分别通过jstat -gcutil ${pid} 1000,和top -p ${pid}查看内存和cpu使用情况,发现内存使用很少,cou使用也很低,排除是java进程内存不够和cpu使用过高问题的原因。

5、查看stage1 reduce阶段的执行计划:

Reduce Operator Tree:
        Extract
          Select Operator
            expressions:
                  expr: _col0
                  type: string
                  expr: _col1
                  type: string
            outputColumnNames: _col0, _col1
            Transform Operator
              command: sh get_recept_mid.sh
              output info:
                  input format: org.apache.hadoop.mapred.TextInputFormat
                  output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
              File Output Operator
                compressed: false
                GlobalTableId: 0
                table:
                    input format: org.apache.hadoop.mapred.SequenceFileInputFormat
                    output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

从执行计划上面看出,stage1的reduce阶段使用了get_recept_mid.sh脚本,该脚本内容如下:

awk -F"\t" 'BEGIN{last=""}{
	if(last!=$1&&last!=""){
		print last"\t"mids
		mids=""
	}

	if(mids==""){
		mids=$2
	}else{
		mids=mids","$2
	}
	last=$1
}END{
	print last"\t"mids
}' /dev/stdin
是一个awk,按理说awk还是很高效的。

既然使用了awk,在运行的时候肯定会起一个进程,我们来查看一下awk进程的内存和cpu使用情况,登陆到运行卡住recue任务的节点,执行top命令,发现确实有一个awk的进程,top -p ${pid},如下图所示:


发现awk实际使用的内存为13M,而且cpu使用达到100.3%,从这两个信息来看应该awk的问题导致reduce被卡住了,以下是找到的awk相关资料:

      “awk有两种工作方式:交互方式及非交互方式。交互方式即输入数据由用户通过键盘输入,此时awk使用行缓冲区,每接收到一行输入数据立即输出。非交互方式的输入数据通过文件或管道输入,此时只有输入缓冲区满了才会输出,对于一些实时性的应用这种方式会带来困扰“

       既然找到了问题的原因就好办了,解决办法将缓冲区的数据刷出去,修改后的脚本内容:

awk -F"\t" 'BEGIN{last=""}{
        fflush("")
        if(last!=$1&&last!=""){
                print last"\t"mids
                mids=""
        }

        if(mids==""){
                mids=$2
        }else{
                mids=mids","$2
        }
        last=$1
}END{
        print last"\t"mids
}' /dev/stdin
从新提交job,发现很快运行完成,reduce被卡住问题解决。

参考:

http://hi.baidu.com/lyugb/item/3351d6100d7e7dfc756a8499

同事博客地址:http://dj1211.com/



hive执行作业时reduce任务个数设置为多少合适

reducer个数的设定极大影响执行效率1. hive.exec.reducers.bytes.per.reducer(默认为1000^3)2. hive.exec.reducers.max(默认为999)计算reducer数的公式很简单:N=min(参数2,总输入数据量/参数1)通常情况下,有必要手动指定reducer个数。考虑到map阶段的输出数据量通常会比输入有大幅减少,因此即使不设定reducer个数,重设参数2还是必要的。依据Hadoop的经验,可以将参数2设定为0.95*(集群中TaskTracker个数)。正确的reduce任务的 个数应该是0.95或者1.75 ×(节点数 ×mapred.tasktracker.tasks.maximum参数值)
 

hive执行作业时reduce任务个数设置为多少合适

遗憾的是Hive的估计机制很弱,不指定reducer个数的情况下,Hive会猜测确定一个reducer个数,基于以下两个设定:1. hive.exec.reducers.bytes.per.reducer(默认为1000^3)2. hive.exec.reducers.max(默认为999)计算reducer数的公式很简单: N=min(参数2,总输入数据量/参数1)通常情况下,有必要手动指定reducer个数。
 

相关内容