Hadoop Definitive Guide --- Chapter 6. How MapReduce Works

来源:互联网 发布:紫金红葫芦淘宝 编辑:程序博客网 时间:2024/06/17 18:21
在本章中我们看看MapReduce具体工作的细节,可以为后面写更高级的程序打下良好的基础。

Anatomy of a MapReduce Job Run
你可以通过如下两种方法来运行MapReduce的Job,submit和waitForCompletion,它包括了很多底层处理的细节,接下来我们看看
它是怎么工作的。

在hadoop0.20和更高的版本上,mapred.job.tracker属性决定了job运行的方式是本地的还是集群的,默认的是Local,如果是地址加端口上
job将会提交给jobtracker去运行。

Classic MapReduce
如下图所示,MapReduce的流程图如下,包括了四个独立的组件
* Client用来提交MapReduce Job的
* Jobtracker用来分配和协调Job的运行,它的主类是JobTracker
* Tasktracker用来运行分配给它的认为,它的主类是TaskTracker
* HDFS用来存储和共享文件的
Hadoop Definitive Guide --- Chapter 6. How MapReduce Works - spring8743 - 我的博客
 

Job Submission
submit()方法创建一个内部的JobSubmitter实例,提交完job之后waitForCompletion()每秒钟获得job运行的情况,将进度显示给控制台,当job
完成的时候,job counter显示给用户,否则的话显示错误的日志信息。
* 从Jobtracker那里获得一个新的jobId
* 坚持job的输出目录,如果输出目录没有指定或者已经存在的话,job不会被执行同时显示错误信息
* 计算当前job的Input Split,如果不能计算比如输入目录不存在,job不会被执行同时显示错误信息
* 复制当前job要运行的所有资源,包括jar包,配置文件,和input split,放到jobtracker的文件系统。
Job的jar包复制10份(mapred.submit.replication)到集群上
* 调用submitJob()告诉Jobtracker准备运行job

Job Initialization
当Jobtracker接受到它的submitJob()方法之后,会把它放到内部的作业队列当中进行初始化。
作业调度器首先接受到从文件系统传过来的计算后的Input Split数量,然后为每个Input Split创建一个
map任务,reduce任务的数量由mapred.reduce.task(默认1)属性决定。
除了map和reduce任务,还有两个任务会被创建,job setup task和job cleanup task。setup任务会
创建最终的输出目录和临时的map输出,cleanup会删除临时的map输出。

Task assignment
Tasktracker会周期性的给jobtracker发心跳,告诉它还存在并且准备接受任务,在它选择task之前,jobtracker会
根据作业调度算法选择一个job。
Tasktracker有个固定数量的槽位给map任务和reduce任务,比如可以配置同时运行两个map任务和两个reduce任务。
这些数量是根据处理器的内核数量和内存的大小。
选择reduce的任务很简单因为没有数据本地化的考虑,但是对于map的任务应该选择离input split最近的tasktracker。

Task execution
现在tasktracker已经分配了一个任务,首先它会将分布式文件系统上的job jar等文件拷贝到本地,然后会创建本地的工作
目录解压jar包,第三步会创建TaskRunner的实例来运行任务。
TaskRunner会启动一个新的JVM线程,所以map或者reduce中的bug不会影响到tasktracker的运行。

Progress and status updates
Mapreduce任务是一个长期的批量任务,时间从数分钟到数小时不等,因此能够给用户反馈进度变的很重要。
每个job和task都会有一个状态(running, successfully completed, failed),进度和计数器。
当任务在运行的时候,它会跟踪整个进度,就是任务完成的百分比。比如map任务,就是处理的输入的字节数的百分比。
Reduce任务就有点复杂,不过系统也可以估计进度,它包括了三部分copy,sort和shuffle。
task会每隔三秒钟将它的进度汇报给tasktracker,同时tasktracker每隔五秒钟给发心跳给jobtracker。jobtracker会汇总所有的
状态信息,每秒钟显示给前台。

Job completion
当jobtracker收到通知说最后一个task完成的时候,它会将状态标志为successful,通知成功的信息给用户,在这时候job的信息和计数器等
显示在控制台里面。


Failures
在现实的世界当中,代码的bug,机器的崩溃等都可以导致任务失败,下面就来考虑常见的错误类型,它包括task failure, tasktracker failure, job tracker failure。

Task failure
最常见的就是用户的代码里面出现了runtime的异常,在这种情况下JVM会发送错误报告给tasktracker,然后退出。

Tasktracker failure
如何tasktracker运行非常的慢或者崩溃,它会停止给jobtracker发送心跳。Jobtracker如果在10分钟之内没有收到心跳,就将它从池中移除。
如果来自同一个job的四个task在指定的tasktracker上失败,将会把它列入黑名单。列入黑名单的tasktracker还会继续发心跳,随着时间的推移
通常是一天,它就会从黑名单上移除而重新获得运行task的机会。

Jobtracker failure
它是一种最严重的失败情况,由于它是个单点,hadoop没有什么好的办法来处理这种情况,此时所有的job都会失败。在重启jobtracker之后所有
未完成的job需要重新提交。不过这种情况在Yarn中得到改进,它可以解决namenode和jobtracker的单点故障问题。

Job Scheduling
在早期的hadoop版本中采用了一种很简单的作业调度机制,FIFO机制根据作业提交的时间先后来决定运行的顺序。后来用户可以自己设置job的优先级,
当jobtracker选择job的时候会优先选择最高级别的job。MapReduce可以自己选择作业调度器,默认的还是传统的基于队列的FIFO,还有公平调度器和容量调度器。

公平调度器的目标就是给每个用户一个公平的共享文件系统等资源的作业调度机制,如果一个任务很长时间没有获得运行,调度器会杀掉一个任务释放资源给它运行。
为了使用它,先将hadoop-fairscheduler-1.2.1.jar放到classpath目录下,然后设置mapred.jobtracker.taskScheduler为org.apache.hadoop.mapred.FairScheduler

容量调度器是一种不同的作业调度方式,一个集群可能有很多的作业队列,作业之间可能有hierachical关系,会根据这个来分配它的容量。

Shuffle and Sort
MapReduce会自动控制将input按照key排序输入到每个reducer,这个过程叫做shuffle。这一小节我们看看它是如何工作的,有个基本的理解是
很重要的,有助于优化你的程序。shuffle是mapreduce的核心,也是神奇发生的地方。

The Map Side
当map函数产生输出的时候,它不是简单的写到磁盘,而是发挥它缓存的优势,先读写到内存然后做预先的排序。
Hadoop Definitive Guide --- Chapter 6. How MapReduce Works - spring8743 - 我的博客
 

每个map会有一个特定的内存缓存大小可以输出,默认的是100M,可以修改io.sort.mb属性。当它的大小达到了一个特定的阈值的时候(默认是0.8),会启动后台的线程
将内容读写到磁盘。溢出会写到由mapred.local.dir属性指定的文件夹内。
在将其写入磁盘之前,线程首先会根据reducer将其切分,然后后台线程会将每个小片在内存中排序,如何有combine的函数,就会在排序之后运行,有助于减少输出到本地磁盘和网络传输。

The Reduce Side
现在让我们看看reduce是怎么工作的,map的输出结果是保持在本地的磁盘上的。reduce可能需要来自不同map上的小切片,但是不同的map完成任务的时间是不一样的,因此一旦完成任务就会启动线程去复制,可以通过mapred.reduce.parallel.copies去修改线程数,默认的是5个线程来copy。
Map的输出会复制到jvm的内存当中,如果很大文件的话会写到磁盘上。当所有的map输出复制完成之后,将会对所有文件进行merge,如果有50个map输出的话,io.sort.factor默认是10,因此需要5轮才会merge完成。在最后一轮并不是通过合并到一个单独的文件,而是直接调用reduce函数输出到单个的文件。在reduce阶段,按照key的排序每个key调用一次函数,结果直接输出到hdfs上。
0 0
原创粉丝点击