快乐学习
前程无忧、中华英才非你莫属!

HADOOP版本说明、与MapReduce模型简介

十、HADOOP版本说明:

     当前Apache Hadoop版本非常多,本小节将帮助读者梳理各个版本的特性以及它们之间的联系。在讲解Hadoop各版本之前,先要了解Apache软件发布方式。

     对于任何一个Apache开源项目,所有的基础特性均被添加到一个称为“trunk”的主代码线(main codeline)。当需要开发某个重要的特性时,会专门从主代码线中延伸出一个分支(branch),这被称为一个候选发布版(candidate release)。该分支将专注于开发该特性而不再添加其他新的特性,待基本bug修复之后,经过相关人士投票便会对外公开成为发布版(release version),并将该特性合并到主代码线中。需要注意的是,多个分支可能会同时进行研发,这样,版本高的分支可能先于版本低的分支发布。

由于Apache以特性为准延伸新的分支,故在介绍Apache Hadoop版本之前,先介绍几个独立产生的Apache Hadoop新版本的重大特性:

     ❑Append[注释]:HDFS Append主要完成追加文件内容的功能,也就是允许用户以append方式修改HDFS上的文件。HDFS最初的一个设计目标是支持MapReduce编程模型,而该模型只需要写一次文件,之后仅进行读操作而不会对其修改,即“write-once-read-many”,这就不需要支持文件追加功能。但随着HDFS变得流行,一些具有写需求的应用想以HDFS作为存储系统,比如,有些应用程序需要往HDFS上某个文件中追加日志信息,HBase需使用HDFS具有的append功能以防止数据丢失[注释]等。

     ❑HDFS RAID[注释]:Hadoop RAID模块在HDFS之上构建了一个新的分布式文件系统:Distributed Raid FileSystem(DRFS)。该系统采用了Erasure Codes增强对数据的保护。有了这样的保护,可以采用更少的副本数来保持同样的可用性保障,进而为用户节省大量存储空间。

     ❑Symlink[注释]:让HDFS支持符号链接。符号链接是一种特殊的文件,它以绝对或者相对路径的形式指向另外一个文件或者目录(目标文件)。当程序向符号链接中写数据时,相当于直接向目标文件中写数据。

     ❑Security[注释]:Hadoop的HDFS和MapReduce均缺乏相应的安全机制,比如在HDFS中,用户只要知道某个block的blockID,便可以绕过NameNode直接从DataNode上读取该block,用户可以向任意DataNode上写block;在MapReduce中,用户可以修改或者删掉任意其他用户的作业等。为了增强Hadoop的安全机制,从2009年起,Apache专门组成一个团队,为Hadoop增加基于Kerberos和Deletion Token的安全认证和授权机制。

     ❑MRv1:第一代MapReduce计算框架。它由两部分组成:编程模型(programmingmodel)和运行时环境(runtime environment)。它的基本编程模型是将问题抽象成Map和Reduce两个阶段。其中,Map阶段将输入数据解析成key/value,迭代调用map()函数处理后,再以key/value的形式输出到本地目录;Reduce阶段则将key相同的value进行规约处理,并将最终结果写到HDFS上。它的运行时环境由两类服务组成:JobTracker和TaskTracker,其中,JobTracker负责资源管理和所有作业的控制,而TaskTracker负责接收来自JobTracker的命令并执行它。

     ❑YARN/MRv2:针对MRv1中的MapReduce在扩展性和多框架支持方面的不足,提出了全新的资源管理框架YARN(Yet Another Resource Negotiator)。它将JobTracker中的资源管理和作业控制功能分开,分别由两个不同进程ResourceManager和ApplicationMaster实现。其中,ResourceManager负责所有应用程序的资源分配,而ApplicationMaster仅负责管理一个应用程序。

     ❑NameNode Federation[注释]:针对Hadoop 1.0中NameNode内存约束限制其扩展性问题提出的改进方案。它将NameNode横向扩展成多个,其中,每个NameNode分管一部分目录。这不仅增强了HDFS扩展性,也使HDFS NameNode具备了隔离性。

     ❑NameNode HA[注释]:HDFS NameNode存在两个问题,即NameNode内存约束限制扩展性和单点故障。其中,第一个问题通过NameNode Federation方案解决,而第二个问题则通过NameNode热备方案(即NameNode HA)实现。

Hadoop版本变迁

到2012年5月为止,Apache Hadoop已经出现四个大的分支,如图2-1所示。

Apache Hadoop的四大分支构成了四个系列的Hadoop版本。

1.0.20.X系列

0.20.2版本发布后,几个重要的特性没有基于trunk而是在0.20.2基础上继续研发。值得一提的主要有两个特性:Append与Security。其中,含Security特性的分支以0.20.203版本发布,而后续的0.20.205版本综合了这两个特性。需要注意的是,之后的1.0.0版本仅是0.20.205版本的重命名。0.20.X系列版本是最令用户感到疑惑的,因为它们具有的一些特性,trunk上没有;反之,trunk上有的一些特性0.20.X系列版本却没有。

0.20.X系列版本却没有。

2.0.21.0/0.22.X系列

这一系列版本将整个Hadoop项目分割成三个独立的模块,分别是Common、HDFS和MapReduce。HDFS和MapReduce都对Common模块有依赖性,但是MapReduce对HDFS并没有依赖性。这样,MapReduce可以更容易地运行其他分布式文件系统,同时,模块间可以独立开发。具体各个模块的改进如下。

❑Common模块:最大的新特性是在测试方面添加了Large-Scale Automated TestFramework[注释]和Fault Injection Framework[注释]。

❑HDFS模块:主要增加的新特性包括支持追加操作与建立符号连接、SecondaryNameNode改进(Secondary NameNode被剔除,取而代之的是Checkpoint Node,同时添加一个Backup Node的角色,作为NameNode的冷备)、允许用户自定义block放置算法等。

❑MapReduce模块:在作业API方面,开始启动新MapReduce API,但老的API仍然兼容。

0.22.0在0.21.0的基础上修复了一些bug并进行了部分优化。

3.0.23.X系列[注释]

0.23.X是为了克服Hadoop在扩展性和框架通用性方面的不足而提出来的。它实际上是一个全新的平台,包括分布式文件系统HDFS Federation和资源管理框架YARN两部分,可对接入的各种计算框架(如MapReduce、Spark等)进行统一管理。它的发行版自带MapReduce库,而该库集成了迄今为止所有的MapReduce新特性。

Spark是一种内存计算框架,支持迭代式计算,主页是http://www.spark-project.org/.

4.2.X系列

同0.23.X系列一样,2.X系列也属于下一代Hadoop。与0.23.X系列相比,2.X系列增加了NameNode HA和Wire-compatibility等新特性。

表2-1总结了Hadoop各个发布版的特性以及稳定性。

十一 Hadoop MapReduce设计目标

通过上一节关于Hadoop MapReduce历史的介绍我们知道,Hadoop MapReduce诞生于搜索领域,主要解决搜索引擎面临的海量数据处理扩展性差的问题。它的实现很大程度上借鉴了谷歌MapReduce的设计思想,包括简化编程接口、提高系统容错性等。总结Hadoop MapReduce设计目标,主要有以下几个。

     ❑易于编程:传统的分布式程序设计(如MPI)非常复杂,用户需要关注的细节非常多,比如数据分片、数据传输、节点间通信等,因而设计分布式程序的门槛非常高。Hadoop的一个重要设计目标便是简化分布式程序设计,将所有并行程序均需要关注的设计细节抽象成公共模块并交由系统实现,而用户只需专注于自己的应用程序逻辑实现,这样简化了分布式程序设计且提高了开发效率。

     ❑良好的扩展性:随着公司业务的发展,积累的数据量(如搜索公司的网页量)会越来越大,当数据量增加到一定程度后,现有的集群可能已经无法满足其计算能力和存储能力,这时候管理员可能期望通过添加机器以达到线性扩展集群能力的目的。

     ❑高容错性:在分布式环境下,随着集群规模的增加,集群中的故障率(这里的“故障”包括磁盘损坏、机器宕机、节点间通信失败等硬件故障和坏数据或者用户程序bug产生的软件故障)会显著增加,进而导致任务失败和数据丢失的可能性增加。为此,Hadoop通过计算迁移或者数据迁移等策略提高集群的可用性与容错性。

十二、 MapReduce编程模型概述

从MapReduce自身的命名特点可以看出,MapReduce由两个阶段组成:Map和Reduce。用户只需编写map()和reduce()两个函数,即可完成简单的分布式程序的设计。

map()函数以key/value对作为输入,产生另外一系列key/value对作为中间输出写入本地磁盘。MapReduce框架会自动将这些中间数据按照key值进行聚集,且key值相同(用户可设定聚集策略,默认情况下是对key值进行哈希取模)的数据被统一交给reduce()函数处理。

reduce()函数以key及对应的value列表作为输入,经合并key相同的value值后,产生另外一系列key/value对作为最终输出写入HDFS。

下面以MapReduce中的“hello world”程序—WordCount为例介绍程序设计方法。

“hello world”程序是我们学习任何一门编程语言编写的第一个程序。它简单且易于理解,能够帮助读者快速入门。

hello world :实战代码详解:http://www.cnblogs.com/xia520pi/archive/2012/05/16/2504205.html

同样,分布式处理框架也有自己的“hello world”程序:WordCount。它完成的功能是统计输入文件中的每个单词出现的次数。在MapReduce中,可以这样编写(伪代码)。

其中Map部分如下:
//key:字符串偏移量
//value:一行字符串内容
map(String key, String value):
//将字符串分割成单词
words=SplitIntoTokens(value);
for each word w in words:
EmitIntermediate(w,"1");
Reduce部分如下:
//key:一个单词
//values:该单词出现的次数列表
reduce(String key, Iterator values):
int result=0;
for each v in values:
result+=StringToInt(v);
Emit(key, IntToString(result));

用户编写完MapReduce程序后,按照一定的规则指定程序的输入和输出目录,并提交到Hadoop集群中。作业在Hadoop中的执行过程如图2-2所示。Hadoop将输入数据切分成若干个输入分片(input split,后面简称split),并将每个split交给一个Map Task处理;Map Task不断地从对应的split中解析出一个个key/value,并调用map()函数处理,处理完之后根据Reduce Task个数将结果分成若干个分片(partition)写到本地磁盘;同时,每个Reduce Task从每个Map Task上读取属于自己的那个partition,然后使用基于排序的方法将key相同的数据聚集在一起,调用reduce()函数处理,并将结果输出到文件中。

细心的读者可能注意到,上面的程序还缺少三个基本的组件,功能分别是:①指定输入文件格式。将输入数据切分成若干个split,且将每个split中的数据解析成一个个map()函数要求的key/value对。②确定map()函数产生的每个key/value对发给哪个Reduce Task函数处理。③指定输出文件格式,即每个key/value对以何种形式保存到输出文件中.

在Hadoop MapReduce中,这三个组件分别是InputFormat、Partitioner和OutputFormat,它们均需要用户根据自己的应用需求配置。而对于上面的WordCount例子,默认情况下Hadoop采用的默认实现正好可以满足要求,因而不必再提供。

综上所述,Hadoop MapReduce对外提供了5个可编程组件,分别是InputFormat、Mapper、Partitioner、Reducer和OutputFormat[注释]。本书将在第3章中详细介绍它们的设计思路以及扩展实现。

同HDFS一样,Hadoop MapReduce也采用了Master/Slave(M/S)架构,具体如图2-5所示。它主要由以下几个组件组成:Client、JobTracker、TaskTracker和Task。下面分别对这几个组件进行介绍。

(1)Client

用户编写的MapReduce程序通过Client提交到JobTracker端;同时,用户可通过Client提供的一些接口查看作业运行状态。在Hadoop内部用“作业”(Job)表示MapReduce程序。一个MapReduce程序可对应若干个作业,而每个作业会被分解成若干个Map/Reduce任务(Task)。

(2)JobTracker

JobTracker主要负责资源监控和作业调度。JobTracker监控所有TaskTracker与作业的健康状况,一旦发现失败情况后,其会将相应的任务转移到其他节点;同时,JobTracker会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可以根据自己的需要设计相应的调度器。

(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的对应关系如图2-6所示。split是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。但需要注意的是,split的多少决定了Map Task的数目,因为每个split会交由一个Map Task处理

                                                      图 2-6 split与block的对应关系

Map Task执行过程如图2-7所示。由该图可知,Map Task先将对应的split迭代解析成一个个key/value对,依次调用用户自定义的map()函数进行处理,最终将临时结果存放到本地磁盘上,其中临时数据被分成若干个partition,每个partition将被一个Reduce Task处理。

                                             图 2-7 Map Task执行流程                                                                   

Reduce Task执行过程如图2-8所示。该过程分为三个阶段①从远程节点上读取Map Task中间结果(称为“Shuffle阶段”);②按照key对key/value对进行排序(称为“Sort阶段”);③依次读取<key, value list>,调用用户自定义的reduce()函数处理,并将最终结果存到HDFS上(称为“Reduce阶段”)。

2.5 Hadoop MapReduce作业的生命周期

由于本书以“作业生命周期”为线索对Hadoop MapReduce架构设计和实现

原理进行解析,因而在深入剖析各个MapReduce实现细节之前整体了解一个作业的生命周期显得非常重要。为此,本节主要讲解Hadoop MapReduce作业的生命周期,即作业从提交到运行结束经历的整个过程。本节只是概要性地介绍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

则该作业的运行过程如图2-9所示。

                                       图 2-9 Hadoop MapReduce作业的生命周期      

这个过程分为以下5个步骤:

     步骤1 作业提交与初始化。用户提交作业后,首先由JobClient实例将作业相关信息,比如将程序jar包、作业配置文件、分片元信息文件等上传到分布式文件系统(一般为HDFS)上,其中,分片元信息文件记录了每个输入分片的逻辑位置信息。然后JobClient通过RPC通知JobTracker。JobTracker收到新作业提交请求后,由作业调度模块对作业进行初始化:为作业创建一个JobInProgress对象以跟踪作业运行状况,而JobInProgress则会为每个Task创建一个TaskInProgress对象以跟踪每个任务的运行状态,TaskInProgress可能需要管理多个“Task运行尝试”(称为“Task Attempt”)。具体分析见第5章。

     步骤2 任务调度与监控。前面提到,任务调度和监控的功能均由JobTracker完成。TaskTracker周期性地通过Heartbeat向JobTracker汇报本节点的资源使用情况,一旦出现空闲资源,JobTracker会按照一定的策略选择一个合适的任务使用该空闲资源,这由任务调度器完成。任务调度器是一个可插拔的独立模块,且为双层架构,即首先选择作业,然后从该作业中选择任务,其中,选择任务时需要重点考虑数据本地性。此外,JobTracker跟踪作业的整个运行过程,并为作业的成功运行提供全方位的保障。首先,当TaskTracker或者Task失败时,转移计算任务;其次,当某个Task执行进度远落后于同一作业的其他Task时,为之启动一个相同Task,并选取计算快的Task结果作为最终结果。具体分析见第6章。

     步骤3 任务运行环境准备。运行环境准备包括JVM启动和资源隔离,均由TaskTracker实现。TaskTracker为每个Task启动一个独立的JVM以避免不同Task在运行过程中相互影响;同时,TaskTracker使用了操作系统进程实现资源隔离以防止Task滥用资源。具体分析见第7章。

     步骤4 任务执行。TaskTracker为Task准备好运行环境后,便会启动Task。在运行过程中,每个Task的最新进度首先由Task通过RPC汇报给TaskTracker,再由TaskTracker汇报给JobTracker。具体分析见第8章。

     步骤5 作业完成。待所有Task执行完毕后,整个作业执行成功。

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » HADOOP版本说明、与MapReduce模型简介

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!