最近微博有一个任务需要使用日曝光表做统计,发现这个任务很容易在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_READ、FILE_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
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/