导读:
1. HDFS架构
2. MapReduce架构
3. MapReduce作业的生命周期
Hadoop的核心两个组件分别是分布式文件系统和分布式计算框架MapReduce。其中分布式文件系统主要用于大规模数据的分布式存储,而MapReduce则构建在分布式文件系统之上,对存储在分布式文件系统中的数据进行分布式计算。在了解MapReduce工作机制之前,考虑到MapReduce的一些功能跟底层存储机制相关,因而会首先介绍分布式文件系统。
Hadoop默认使用的分布式文件系统是HDFS(Hadoop Distributed File System),它与MapReduce框架紧密结合。HDFS是一个具有高容错性的分布式文件系统,适合部署在廉价的机器上,能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。
HDFS的框架总体采用了master/slave架构,主要由以下几个组件组成:Client、NameNode、SecondNamenode和DataNode。下面分别对这几个组件进行介绍。
(1)Client
Client是客户端,是用户操作HDFS最常用的方式,通过与NameNode和DataNode交互从而访问HDFS中的文件。
(2)NameNode
NameNode是名字节点,整个Hadoop集群中只有一个NameNode。它是整个系统的“总管”,负责管理HDFS的目录树和相关的文件元数据信息。这些信息是以“fsimage”(HDFS元数据镜像文件)和“editlog”(HDFS文件改动日志)两个文件形式存放在本地磁盘,当HDFS重启时重新构造出来的。此外,NameNode还负责监控各个DataNode的健康状态,一旦发现某个DataNode宕掉,则将该DataNode移出HDFS并重新备份其上面的数据。
(3)Second NameNode
Second NameNode最重要的任务并不是为NameNode元数据进行热备份,而是定期合并fsimage和edits日志,并传输给NameNode。这里需要注意的是,为了减小NameNode压力,NameNode自己并不会合并fsimage和edits,并将文件文件存储到磁盘上,而是交由Second NameNode完成。
(4)DataNode
一般而言,每个Slave节点上安装一个DataNode,它负责实际的数据存储,并将数据信息定期汇报给NameNode。DataNode以固定大小的block为基本单位组织文件内容,默认情况下block大小为64MB。当用户上传一个大的文件到HDFS上时,该文件会被切分成若干个block,分别存储到不同的DataNode。同时,为了保证数据可靠,会将同一个block以流水线方法写到若干个(默认是3个,该参数可配置)不同的DataNode上。
Hadoop MapReduce采用Master/Slave(M/S)架构,如下图所示,主要包括以下组件:Client、JobTracker、TaskTracker和Task。
(1)Client
用户编写的MapReduce程序通过Client提交到JobTracker端;同时,用户可通过Client提供的一些接口查看作业运行状态。在Hadoop内部用“作业”(Job)表示MapReduce程序。一个MapReduce程序可对应若干个作业,而每个作业会被分解成若干个Map/Reduce任务(Task)。
(2)JobTracker
JobTracker主要负责资源监控和作业调度。JobTracker监控所有TaskTracker与作业的健康状况,一旦发现失败情况后,其会将相应的任务转移到其他节点;同时JobTracker会跟踪任务的执行进度、资源使用量等,并将这些信息告诉给任务调度器(Task Scheduler),而T调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可以根据自己的需要设计相应的Scheduler。
(3)TaskTracker
TaskTracker会周期性地通过Heartbeat将本节点上资源的使用情况和任务的运行进度汇报给JobTracker,同时接收JobTracker发送过来的命令并执行相应操作(如启动新任务、杀手任务等)。TaskTracker使用“slot”等量划分本节点上的资源量。“slot”代表计算资源(CPU、内存等)。一个Task获取到一个slot后才有机会运行,而Hadoop调度器的作用就是将各个TaskTracker上的空闲slot分配给Task使用。slot分为Map slot和Reduce slot两种,分别供Map Task和Reduce Task使用。TaskTracker通过slot数目(可配置参数)限定Task的并发度。
(4)Task
Task分为Map Task和Reduce Task两种,均由TaskTracker启动。我们知道,HDFS以固定大小的block为基本单位存储数据,而对于MapReduce而言,其处理单位是split。split与block的对应关系如下图所示。split是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。但需要注意的是,split的多少决定Map Task的数目,因为每个split会交由一个Map Task处理。
(4-1)Map Task的执行过程
Map Task先将对应的split迭代解析成一个个key/value对,依次调用用户自定义的map()函数进行处理,最终将临时结果存放到本地磁盘上,其中临时数据被分为若干个partition,每个partition将被一个Reduce Task处理。
(4-2)Reduce Task的执行过程
Map Task执行过程分为三个阶段①从远程节点上读取Map Task的中间结果(称为“Shuffle阶段”);②按照key对key/value键值对进行排序(称为“Sort阶段”);③依次读取
MapReduce作业的生命周期包括作业从提交到运行结束经历的整个过程。假设用户编写一个MapReduce程序,并将其打包成xxx.jar文件,然后提交作业:
$HADOOP_HOME/bin/hadoop jar xxx.jar
-D mapred.job.name=”xxx” \
-D mapred.map.tasks=3 \
-D mapred.reduce.tasks=2 \
-D input=/test/input \
-D output=/test/output
则该作业的运行过程如下图所示
这个过程分为一下5个步骤:
步骤1:作业提交与初始化。
用户提交作业后,首先由JobClient实例将作业相关信息,比如将程序jar包、作业配置信息、分片原信息文件等上传到分布式文件系统(一般为HDFS)上,其中,分片信息文件记录了每个输入分片的逻辑位置信息。然后JobClient通过RPC通知JobTracker。JobTracker收到新作业提交请求后,由作业调度模块对作业进行初始化:为作业创建一个JobInProcess对象以跟踪作业运行状况,而JobInProcess则会为每个Task创建一个TaskInProgress对象以跟踪每个任务的运行状态,TaskInProgress可能需要管理多个“Task运行尝试”(成为“Task Attempt”)。
步骤2:任务调度与监控。
任务调度和监控均由JobTracker完成。TaskTracker周期性地通过Heartbeat向JobTracker汇报本节点的资源使用情况,一旦出现空闲资源,JobTracker会按照一定的策略选择一个合适的任务使用该空闲资源,这个过程由任务调度器完成。任务调度器是一个可插拔的独立模块,且为双层架构,即首先选择作业,然后从该作业中选择任务,其中,选择任务时需要重点考虑数据本地性。此外,JobTracker跟踪作业的整个运行过程,并为作业的成功运行提供全方位的保障。首先,当TaskTracker或者Task失败时,转移计算任务;其次,当某个Task执行进度远落后于同一个同一个作业的其他Task时,为之启动一个相同的Task,并选择计算快的Task结果作为最终结果。
步骤3:任务运行环境准备。
运行环境准备包括JVM启动和资源隔离,均由TaskTracker实现。TaskTracker为每个Task启动一个独立的JVM以避免不同Task在运行过程中相互影响;同时,TaskTracker使用操作系统进程实现资源隔离以防Task滥用资源。
步骤4:任务执行。
TaskTracker为Task准备好运行环境后,便会启动Task。在运行过程中,每个Task的最新进度首先由Task通过RPC汇报TaskTracker,再由TaskTracker通过RPC汇报给JobTracker。
步骤5:作业完成。
待所有Task执行完毕后,整个作业执行成功。
【参考资料】
[1] 董西成,《Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》
[2] yr123,MapReduce程序的工作过程:
http://www.aboutyun.com/thread-15494-1-2.html