JobTracker是整个集群中唯一的全局管理者,涉及的功能包括作业控制和资源管理。
作业控制模块负责作业的分解和状态监控
状态监控(容错,任务调度)
- TaskTracker状态监控
- 作业状态监控
- 任务状态监控
作业控制
JobTracker在其内部以“三层多叉树”的方式描述和跟踪每个作业的运行状态
-
1、作业控制层
- 每个作业由一个JobInProgress(JIP)对象描述和跟踪其整体运行状态以及每个任务的运行情况 2、任务监控层
- 每一个任务有一个TaskInProgress(TIP)对象描述和跟踪其运行状态 3、 任务执行层
- 任务被反复执行直到成功
- 每一次尝试运行的任务实例称为Task Attempt(TA)
- 当任何一个TA运行成功后,其上层对应的TIP会标注该任务运行成功
- 当所有TIP运行成功后,JIP标注整个作业运行成功
- 为了根据作业ID找到对应的JIP对象,JobTracker将所有运行作业按照JobID与JIP对应关系保存到Map数据结构jobs中
- 为了能够查找每个TaskTracker上当前正在运行的Task,JobTracker将trackerID与TaskID集合的映射关系保存到Map数据结构trackerToTaskMap中
-
容错功能
- 通过监控信息推测出“拖后腿”任务,通过启动备份任务加快数据处理速度
- 通过各阶段记录日志辅助JobTracker在发生故障时进行作业恢复 资源管理
- JobTracker通过TaskTracker周期性发来的状态信息,为TaskTracker分配最合适任务。
ACLsManager
- 权限管理类,提供了checkAccess方法对用户的各种操作进行权限检查
- 涉及队列权限管理(QueueManager类)和作业权限管理(JobACLsManager类)
- QueueManager类:队列权限管理类。包括作业提交权限权限与作业管理权限(管理权限与权限管理)
- JobACLsManager类:作业权限管理类。作业查看权限以及作业修改权限。
HttpServer类
Hadoop对外提供Web服务的HTTP服务器
DNSToSwitchMapper类
定义了将DNS名称或者节点IP地址转化成网络位置的规则。Hadoop以层次树的方式定义节点的网络位置,并根据该位置存取数据或者调度任务。
/dcX/rackX/nodeX
表示数据中心dcX中,机架rackX上的节点nodeX。
可以通过topology.script.file.name
指定ScriptBasedMapping识别转换规则。
JobTracker后台服务线程
expireTrackersThread
- 用于发现和清理死掉的TaskTracker。
- 每10分钟内未向JobTracker汇报信息对的TaskTracker将会被从数据结构(trackerToJobsToCleanup,trackerToTasksTocleanup,trackerToTaskMap,trackerToMarkedTasksMap)中清除
- 正常运行中的任务被标记为
KILLED_UNCLEAN
retireJobsThread
- 用于清理长时间占用内存的已完成作业信息
- 原本将已完成作业放在内存中是为了方便查询,但作业量会越来越多,占用内存也会增加
- 清理条件:
- (必备)完成状态为
SUCCEEDED
,FAILD
或KILLED
之一 - (达成其一)作业完成超过
mapred.jobtracker.retirejob.interval=24
小时;已完成作业数超过mapred.jobtracker.completeuserjobs.maximum=100
- (必备)完成状态为
- 过期作业会被保存在过期队列中,过期队列长度超过
mapred.job.tracker.retirejobs.cache.size=1000
则会被从内存中删除
expireLaunchingTaskThread
- 用于已经分配给TaskTracker但未汇报的任务
- 要求分配后10分钟内汇报进度,未汇报则标记为
FAILDED
completedJobsStoreThread
- 将已完成作业信息(运行日志)保存到HDFS上,并提供存取API
- 与存放内存不同,线程持久化作业信息,不会因为内存过期或JobTracker重启而消失。
配置参数 | 参数含义 |
---|---|
mapred.job.tracker.persist.jobstatus.active | 是否启用该线程(默认为否) |
mapred.job.tracker.persist.jobstatus.hours | 作业运行信息保存时间 |
mapred.job.tracker.persist.jobstatus.dir | 作业运行信息保存路径 |
TaskTracker与JobTracker交互(心跳)
- RPC函数
- TaskTracker调用函数汇报节点信息和任务状态信息
- TaskTracker主动汇报和获取,而非JobTracker主动询问
Heatbeat函数内部逻辑主要分为更新状态和下达命令两个步骤
public synchronized HeartbeatResponse heartbeat(TaskTrackerStatus status,
boolean restarted,
boolean initialContact,
boolean acceptNewTasks,
short responseId)
函数返回了一个HeartbeatResponse对象,主要封装了JobTracker向TaskTracker下达的命令。
JobTracker状态监控
JobTracker内部以三层多叉树方式描述和跟踪每个作业的运行状态:
- 为每个作业创建一个JIP以跟踪监控,存在于作业运行的整个过程中(提交时创建,运行完成时销毁)
- JobTracker会将作业拆分成若干个任务,每个任务创建一个TIP以跟踪监控
- 一个TIP会有多次任务运行尝试Task Attempt(TA)直到成功
作业状态转换(由JIP控制)
状态1 | 状态2 | 含义 |
---|---|---|
PREP | RUNNING | 作业的Setup Task成功执行完成 |
RUNNING | SUCCEEDED | 作业的Cleanup Task执行成功 |
PREP | FAILED、KILLED | 人为使用shell杀死作业 |
RUNNING | FAILED | 如:人为shell杀死;Cleanup,Setup运行失败;失败任务数过多 |
RUNNING | KILLED | 人为shell杀死 |
任务状态转换(并非由TIP控制,发生在任务运行的任何时候)
状态1 | 状态2 | 含义 |
---|---|---|
UNASSIGNED | RUNNING | JobTracker将某个任务分配给TaskTracker,TaskTracker准备运行环境并启动任务 |
RUNNING | COMMIT_PENDING | 产生于Reduce Task和map-only的Map Task。 任务处理完最后一条记录进入该状态,等待JobTracker批准其提交结果 |
RUNNING | SUCCEEDED | 只存在于Map Task,且将给Reduce Task处理。Map Task处理完最后一条记录后意味着任务运行成功 |
RUNNING,COMMIT_PENDING | KILLED_UNCLEAN | |
RUNNING,COMMIT_PENDING | FAILED_UNCLEAN | |
UNASSIGNED | FAILED,KILLED | |
KILLED_UNCLEAN,FAILED_UNCLEAN | FAILED,KILLED | |
SUCCEEDED | KILLED | |
SUCCEEDED,COMMIT_PENDING | FAILED |
容错机制
JobTracker容错
- 1.1.0版本,任务级别恢复机制
- 0.21.0版本,作业级别恢复机制
TaskTracker容错
1、 超时机制
- TaskTracker第一次汇报心跳后,JobTracker会将其放入过期队列trackerExpiryQueue中,并加入网络拓扑结构
- expireTrackersThread负责处理,清除队列中未汇报的任务
-
特殊情况重新加入等待队列:
- a) 作业处于运行或等待状态;
- b) 未运行完成的Map Task或者Reduce Task或Map Task已经完成但Reduce Task未完成的任务。
- *因为正常的TaskTracker无法通过HTTP获取死亡TaskTracker上的本地磁盘数据
2、 灰名单、黑名单机制(TaskTracker级别)
- 在两种名单之中均不可再接收作业,有可能是服务故障,也有可能只是性能下降
- 加入灰名单的TaskTracker过一段时间仍可以重新尝试加入工作
-
黑名单
- 通过health check script对TaskTracker进行监控,结果汇报给JobTracker
-
当TA的失败数目超过
mapred.max.tracker.failures=4
时,TA所在的TaskTracker将被加入和名单 - 被加入黑名单的TaskTracker,JobTracker不向其分配任务 灰名单
- 位于黑名单中的TaskTracker同时满足以下条件才会被加入灰名单
-
a) 黑名单大小超过
mapred.max.tracker.blacklist=4
(黑名单过大) -
b) 某个TaskTracker的黑名单占总TaskTracker黑名单的
mapred.cluster.average.blacklist.threshold=0.5
倍(特定一个黑名单过大) - c) 灰名单大小小于总TaskTracker数目的50%(灰名单还有空间) 环形桶结构
- 暂时留空
3、 Exclude list、Include list(host级别)
-
Exclude list
- 非法节点(一个host可能有多个TaskTracker)列表,节点无法与JobTracker连接,由RPC层抛出异常,默认为空 Include list
- 合法节点列表,只有在白名单中才能发起连接请求,默认为空(表示任何节点均允许连接)
Job,Task容错
-
Job容错
-
通过配置
mapred.max.map.failures.percent=0
和mapred.max.reduce.failures.percent=0
参数来设定允许失败的Map Task和Reduce Task占总任务数的百分比,默认一个任务失败则整个作业失败。
Task容错
-
多次的Task Attempt尝试,通过配置
mapred.map.max.attempts=4
和mapred.reduce.max.attempts=4
最大尝试次数,当超过最大尝试次数则记为失败(FAILED,KILLED)。 - FAILED:人为杀死,本地文件读写错误,shuffle阶段错误,Counter数目过多,一定时间内未上报进度,内存量过大,其他错误
- KILLED:人为杀死,磁盘空间或内存不足,TaskTracker丢失(未上报进度)
失败类型\场景 | 同节点调度 | 允许失败次数 |
---|---|---|
KILLED | 可以 | 不限 |
FAILED | 不可以 | 有限 |
Record容错
能够记录前几次任务尝试中导致失败的Record,并在下次运行时自动跳过这些坏记录。
常见原因1,key或value过大导致的OOM
- 在InputFormat组件中设置key或者value的最大长度,超过长度将会被截断
- 在TextInputFormat配置参数
mapred.linerecordreader.maxlength
常见原因2,第三方java包或者库的bug导致记录处理失败,导致任务崩溃或阻塞
- 通过配置SkipBadRecord参数控制坏记录跳过机制
参数名称 | 参数含义 | 默认值 |
---|---|---|
mapred.skip.attempts.to.start.skipping | 当任务失败次数超过该值时,才会进入skip mode,即启用跳过坏记录功能 | 2 |
mapred.skip.map.max.skip.records | Map Task最多允许跳过的记录数目 | 0 |
mapred.skip.reduce.max.skip.groups | Reduce Task最多允许跳过的记录数目 | 0 |
mapred.skip.out.dir | 检测出的坏记录存放目录(一般为HDFS路径) | ${mapred.output.dir}/_logs/ |
(略过跳过坏记录的详细过程)
磁盘容错
-
TaskTracker的磁盘均衡策略
- 轮询(默认)
- 随机选择
- 最多剩余磁盘空间优先
TaskTracker采用的磁盘容错机制
mapred.local.dir.minspacestart
,TaskTracker需要保证的最小磁盘可用空间,大于该值时才会接受任务mapred.local.dir.minspacekill
,TaskTracker会周期性检查节点的剩余磁盘空间,小于该值则按照一定策略将正在运行的任务杀掉以释放空间- TaskTracker启动时检查Map Task中间结果输出目录
mapred.local.dir
,使用其中的健康目录,以mapred.disk.healthChecker.interval=60
为周期检查个目录健康状况,一旦发现异常则对自己重新初始化。
JobTracker采用的磁盘容错机制
- 由于保存了所有任务的运行信息,可以根据完成的任务产生的数据量估算其他相同作业所需的磁盘空间
- 运行Map Task数量超过总数的1/10时,开始估算剩余任务的磁盘使用量
- 简单线性模型:
预计所有Map输出=总输入∗已完成输出已完成输入∗2 预 计 所 有 M a p 输 出 = 总 输 入 ∗ 已 完 成 输 出 已 完 成 输 入 ∗ 2
预计单个Map输出=预计所有Map输出Map任务数量 预 计 单 个 M a p 输 出 = 预 计 所 有 M a p 输 出 M a p 任 务 数 量
预计单个Reduce输入=预计所有Map输出Reduce任务数量 预 计 单 个 R e d u c e 输 入 = 预 计 所 有 M a p 输 出 R e d u c e 任 务 数 量
当估算完之后,发现某个Map或者Reduce任务的输入或者输出超过所在TaskTracker的剩余磁盘空间,则不会将任务分配给该TaskTracker。
推测执行
- 用于推测出处理速度明显慢于其他任务的任务,这些任务拖慢了整体的执行进度。
- 可能是因为程序bug,负载不均衡或者资源分布不均等原因导致同一个作业在多任务之间处理速度不一致
- Hadoop会为预测处理速度较慢的任务(还未执行)启动备份任务与原始任务同时开始,取最快完成的任务的结果
mapred.map.tasks.speculative.execution=true
用于控制Map Task的推测执行功能mapred.reduce.tasks.speculative.execution=true
用于控制Reduce Task的推测执行功能
Hadoop资源管理
- 资源表示模型,采用槽位(slot)组织各节点上的资源
- 资源分配模型,使用插拔式调度器完成
资源表示模型
- Hadoop将各个节点上的资源(CPU,内存,磁盘等)等量切分成若干份,每一份用一个slot表示,同时规定一个Task可根据实际需要占用多少个slot。
- 只有占有slot的时候才能执行任务
- 每个节点的slot数目决定了该节点的最大任务并发度
- 分为Map slot(由
mapred.tasktracker.map.tasks.maximum
配置)和Reduce slot(由mapred.tasktracker.reduce.tasks.maximum
配置)
资源分配模型
步骤3 某个TaskTracker向JobTracker汇报心跳,其中包含剩余的slot数和能否接受新任务等信息。
步骤5 TaskScheduler按照一定的调度策略选择最合适的任务列表(tasks list),并将该列表返回给JobTracker
步骤6 JobTracker将task list以心跳应答的形式返回给对应的TaskTracker
调度器(TaskScheduler)
三级调度模型:
1. 队列调度
2. 作业调度
3. 任务调度(主要考虑数据本地性)
可以通过mapred.jobtracker.taskScheduler
配置不同任务调度器(常用FIFO,Capacity Scheduler, Fair Scheduler),主要区别在于队列选择与作业选择策略的不同。
任务调度
数据本地性
根据输入数据与实际分配的计算资源之间的距离,将任务分成三类:- node-local,同节点
- rack-local,不同节点同机架
- off-switch,跨机架
距离越远,网络开销越大,因此优先级自上而下。
Map Task选择策略
- Reduce Task选择策略
资源管理优化
- 基于动态slot(slot可以在TaskTracker间调度)
- 基于无类别(不区分Map slot 还是Reduce slot)
- 基于真实资源需求量