为了给各个业务出报表,我们每天会处理几百亿条原始日志。例行任务用MR/Spark程序编写,为了保证各业务线在上班前正常看到数据,对例行任务的稳定性提出了要求。由于我们会依赖很多中间层数据,集群偶尔异常、数据存在倾斜等问题,这对我们的程序带来了很大的挑战。针对遇到的问题,采用“兵来将挡,水来土掩”的方案,各个击破
当天任务依赖的数据,部分是前一天的数据,部分是当天其他任务生成的数据。可以采用这两种方案。
依赖的前一天的数据可能没生成。为了避免第二天的例行任务不挂掉,需要在前一天下午到晚上添加监控,如果数据没有按时生成,就发告警。然后由程序的owner来推动数据尽快产生。
function hdfs_check() {
file=$1
hadoop fs -test -e ${file}/_SUCCESS
if [ $? -ne 0 ]; then
send_mms "[FATAL]-[file_not_exists]-[${file}]" yanghao
fi
}
function main() {
date=`date -d "-1day" '+%Y%m%d'`
hdfs_check /user/yanghao/device_middle/date=${date}
}
依赖的数据可能生成延迟,启动MR和Spark任务时,可以检查依赖是否生成,如果未生成,则一直等待,直到任务数据生成再启动
数据倾斜会导致部分task的数据膨胀,进而导致内存溢出、任务变慢等后果。主要有下面几种方案来避免。
设计时考虑可能存在的倾斜问题,保证shuffle后各个key对应的数据量尽量均匀。
集群偶尔抖动,导致任务失败,但是重启问题能解决。这样可以在启动程序后,监控程序的返回值,如果失败,则重试。如果是MR,一般是waitForCompletion提交的,返回值表示是否正确执行,如果为false,则在代码中重新提交任务
本文总结了在生产环境中导致任务失败的常见case,并一一介绍了解决方案。当然报表未按时出来,还可能遇到其他问题,比如DB挂了,这就需要具体问题具体分析了。