6.5.3 Job/Task容错
1.Job容错机制
在MapReduce框架中,一个作业会被分解成多个任务,当所有任务成功运行完成时,作业才算运行成功。但在很多实际应用场景中,比如搜索引擎日志分析、网页处理等,由于数据量巨大,丢弃一小部分数据可能并不会影响最终结果。正因为如此,为支持容错,MapReduce允许丢弃部分输入数据而保证绝大部分数据有效,也就是说,MapReduce可允许部分任务失败,而其对应的处理结果不再计入最终的结果。
Hadoop为作业提供了两个可配置参数:mapred.max.map.failures.percent和mapred.max.reduce.failures.percent。用户提交作业时可通过这两个参数设定允许失败的Map任务和Reduce任务数所占总任务数的百分比。默认情况下,这两个参数值均为0,即只要有一个Map任务或者Reduce任务失败,整个作业便运行失败。
2.Task容错机制
前面提到,每个Task运行状况由对应的一个TaskInProgress对象跟踪,它允许一个Task尝试运行多次,每次称为一个运行尝试,即Task Attempt。Hadoop提供了两个可配置参数:mapred.map.max.attempts和mapred.reduce.max.attempts。用户提交作业时可通过这两个参数设定Map Task和Reduce Task尝试运行最大次数。默认情况下,这两个值均为4,即每个Task可最多运行4次,如果尝试4次之后仍旧未运行成功,则TaskInProgress对象将该任务运行状态标注为FAILED。
未运行成功的Task Attempt可分为两种:killed task和failed task,它们分别对应状态KILLED和FAILED。其中,killed task是MapReduce框架主动杀死的Task Attempt,一般产生于以下3种场景。
❑人为杀死Task Attempt:用户使用命令“bin/hadoop job-kill-task<task-id>”将一个Task Attempt杀死。
❑磁盘空间或者内存不够:任务运行过程中,出现磁盘或者内存磁盘不足,MapReduce框架需采用一定策略杀死若干个Task以释放资源。其选择杀死Task的策略是优先选择Reduce Task,其次是进度最慢的Task。
❑TaskTracker丢失:如果TaskTracker在一定时间内未向JobTracker汇报心跳,则JobTracker认为该TaskTracker已经死掉,它上面的所有任务将被杀掉。
Failed task是自身运行失败的Task Attempt,通常产生于以下几种场景。
❑人为使Task Attempt失败:用户使用命令“bin/hadoop job-fail-task<task-id>”使一个Task Attempt杀死。
❑本地文件读写错误:Task运行过程中,由于磁盘坏道等原因,导致文件读写错误。
❑Shuffle阶段错误:Reduce Task从Map Task端远程读取数据过程中出错。
❑Counter数目过多:用户自定义的Counter或者Counter Group数目超过系统要求的上限。
❑一定时间内未汇报进度:由于程序Bug或者数据格式问题,任务在一定时间间隔(可通过参数mapred.task.timeout配置,默认10分钟)内未汇报进度。
❑使用内存量超过期望值:用户提交作业时可指定每个Task预期使用的内存量,如果在运行过程中超过该值,则会运行失败。
❑任务运行过程中的其他错误:如初始化错误,其他可能的致命错误。
Failed task和killed task除了产生场景不同以外,还有以下两个重要区别。
❑调度策略:一个Task Attempt在某个节点上运行失败之后,调度器便不会再将同一个Task的Task Attempt分配给该节点;而一个Task Attempt被杀掉后,仍可能被调度到同一个节点上运行。
❑尝试次数:前面提到的Task容错机制是针对failed Task的,也就是说,任何一个Task允许的失败次数是有限的;而对于killed Task,由于它们是被框架主动杀死的,它们自身并不存在问题,因此会不断尝试运行,直到运行成功。