本文固定链接:https://www.askmac.cn/archives/hadoop-concepts.html
Hadoop概念
应用程序经常需求,超过廉价(商品)机器上可用的更多资源。许多组织发现自己的业务流程不再适合在单一的、具有成本效益的计算机上进行。一个简单却昂贵的解决方案是购买耗费大量内存,并具有多个CPU的专门机器 。该解决方案可最快扩展至机器所支持的程度,但是唯一的限制因素通常是你的预算。另一种解决方案是建立一个高可用性集群,它通常试图看起来像一个单台机器,并且通常需要非常专业化的安装和管理服务。许多高可用性集群都是有版权并且昂贵的。
获取必要的计算资源的一种更经济的解决方案是云计算。一种常用模式是:那些需要被转换的批量数据,其中每个数据项的处理基本上独立于其他数据项;也就是说,通过使用单指令,多数据(SIMD )方案。Hadoop提供一个云计算的开源框架,以及一个分布式文件系统。
本书的设计意图是作为使用Hadoop,一个由Apache软件基金会主办的项目,来开发和运行软件的实用指南。本章将为你介绍Hadoop的核心概念。目的是为下一章的内容做准备,下一章中你将了解Hadoop的安装和运行(www.askmac.cn)。
Hadoop介绍
Hadoop是以发表于2004年的有关MapReduce的Google文章为基础,其发展始于2005年。当时,Hadoop的开发是为了支持一个叫做Nutch的开源网络搜索引擎项目。最终,Hadoop从Nutch中分离出来,成为Apache基金会下自己的一个项目。
今天Hadoop是市场上最知名的MapReduce框架。目前,有几家围绕Hadoop的公司已经发展到提供Hadoop软件的支持、咨询和培训服务。
Hadoop的核心是一个基于Java的MapReduce框架。然而,由于Hadoop平台的迅速普及,支持非Java用户群体很有必要。Hadoop已经发展到拥有以下改进,和支持该群体的子项目,并将其范围扩大到企业。
- Hadoop Streaming:可以使用任何命令行来启用MapReduce。这使得MapReduce可被UNIX脚本程序、Python程序等使用,以开发ad hoc作业。
- Hadoop Hive:MapReduce的用户很快意识到,开发MapReduce程序是一个编程非常密集的任务,这使得它容易出错,并且很难测试。有必要使用更具表达性的语言,例如SQL可以使用户将注意力集中在问题上而非典型SQL工件的底层实现上(例如,WHERE子句, GROUP BY子句, JOIN子句等)。Apache Hive发展到为大型数据集提供数据仓库(DW )功能。用户可用Hive查询语言表达他们的查询,这与SQL非常类似。Hive引擎将这些查询透明地转换为MapReduce底层任务。更高级的用户可在Java中开发用户自定义函数(UDF)。Hive支持标准驱动程序,如ODBC和JDBC。为存储在Hadoop中的数据开发Business Intelligence(BI)类型的应用程序时,Hive也是一个合适的平台(www.askmac.cn)。
- Hadoop Pig: 虽然Pig的动机类似于Hive,Hive是一种类似于SQL的语言,另一方面,Pig是一种在数据 – 管道方案中运作良好的程序语言。Pig会吸引开发数据处理管道的程序员(如SAS程序员)。它也是一个用于提取、加载和转换(ELT)类型的应用程序的适当平台。
- Hadoop HBase: 上述所有项目,包括MapReduce,都是批处理。而Hadoop中对于实时数据查找有强烈需求。Hadoop没有本地键/值存储。例如,思考一个社交媒体网站如Facebook。如果你想查找一个朋友的个人资料,你肯定希望立即得到答案(而不是经过很长一段时间的批处理任务运行之后)。这些用例就是开发HBase平台的动机。
我们才刚刚触及Hadoop及其子项目的功能。不过前面的例子说明了Hadoop为什么按照它从前的方式发展。Hadoop作为MapReduce引擎启用,开发的目的是为了索引大量文本数据。它慢慢演变成一种通用的模式,以支持标准企业用例,如DW, BI, ELT和实时查询缓存。MapReduce是一个非常有用的模型,它适应于刚才所述类型(ETL,DW)的标准企业用例,这使得它能够渗透到主流计算市场。同样重要的是,企业正努力克服处理海量数据的问题。
在很长一段时间内,Hadoop是在整个集群上提交任务的系统。任务将以先入先出(FIFO)的方式被执行。但这会导致一个长期、不太重要的任务占用资源,而且使得一个更小但更重要的任务无法执行。为了解决这一问题,Hadoop会创建复杂的作业调度程序,如Fair Scheduler和Capacity Scheduler。但Hadoop 1.x(在版本0.23之前)仍存在可扩展性限制,这是一些比较根深蒂固的设计所带来的后果(www.askmac.cn)。
Yahoo工程师发现,当节点数量增加到几千时Hadoop存在可扩展性问题。( http://developer.yahoo.com/blogs/hadoop/scaling-hadoop-4000-nodes-yahoo-410.html )。随着这些问题变得更易理解,Hadoop的工程师们又回到了绘图板,并重新评估原Hadoop底层设计的一些核心假设,最终导致核心Hadoop平台的一次大的设计修改。Hadoop 2.x(出自Hadoop 0.23版本)就是这次修改的成果。
本书将涵盖版本2.x以及对1.x的一些适当引用,如此你就可体会到版本2.x变化背后的动机。
介绍MapReduce模型
Hadoop支持MapReduce模型,它是由谷歌推出的,用大型集群的商品机解决一类计算机问题的方法。该模型是基于两个不同的步骤,两者的应用程序都是自定义和用户定义的:
- Map:初始摄取和转换步骤,其中各个输入记录可并行处理。
- Reduce: 聚合或总结步骤,其中所有相关记录必须由一个单一实体一起处理(www.askmac.cn)。
Hadoop中MapReduce的核心概念是,输入可分割成逻辑chunks,每个chunk可由一个map任务独立处理。这些个别处理chunk的结果可物理划分到不同的集和,然后将其排序。每个被排序的chunk被传递到一个reduce任务。图2-1说明了MapReduce模型是如何工作的。
图2-1 MapReduce模型
map任务可在集群中的任何计算节点上运行,且多个map任务可在集群间并行运行。map任务负责将输入记录转换成键/值对。所有map的输出将被分区,且对每个分区进行排序。每个reduce任务有一个分区。每个分区的排序键和与键相关的值随后由reduce任务进行处理。可有多个reduce任务在集群上并行运行。
通常情况下,应用程序开发人员仅在Hadoop框架上提供四项:读取输入记录,并将其转换成每个记录一个键/值对的类,一个Mapper类,一个Reducer类,和一个将reduce方法输出的键/值对转换为输出记录的类。
让我们用现已成为MapReduce模型“Hello-World”的计数应用程序来说明MapReduce的概念(www.askmac.cn)。
试想一下,假如你有大量的文本文档。随着大家对分析非结构化数据兴趣的日益增加,现在这种情况已比较常见。这些文本文档可以是从以下网站:http://dumps.wikimedia.org/下载的维基百科页面。或者可能是一个用于法律目的的大企业电子邮件归档(例如,Enron Email数据集:www.cs.cmu.edu/~enron/)。有许多有趣的分析可在文本上执行(例如,信息提取,基于内容的文档聚类,基于情感的文档分类)。然而,大多数这样的分析都以统计文档语料库中的字数开始(文档的集合通常被称作一个语料库)。其中一个原因是为了计算一个词/文档组合中的词频/倒排文档频率(TF / IDF)。
- 注意 有关tF/IdF的详细讨论以及一些相关的应用程序可在以下链接中找到:http://en.wikipedia.org/wiki/Tf-idf
直观上来说,这应该很容易做到。假设为简单起见,每个文档包含按空格隔开的词。一个简单的解决方案是:
- 维护一个哈希表,它的键是一个“词”,值是词的计数。
- 将每个文档加载到内存中
- 将每个文档拆分为词
- 为文档中每个词更新全局哈希表。
- 每个文档被处理后,我们拥有所有词的计数(www.askmac.cn)。
大多数语料库在几百万个中拥有其独一无二的计数,所以前面的解决方案在逻辑上是可行的。然而,最需要注意的是数据的大小(毕竟本书是关于大数据的)。当文档语料库是TB级的规模,它可能需要几个小时甚至几天才能在单个节点上完成流程。
因此,当数据规模很大时我们使用MapReduce解决这一问题。注意:这是你通常会遇到的情况,当你有一个非常简单只是无法在一台机器上扩展的问题时,应该使用MapReduce。
上述解决方案的MapReduce实现如下所示:
- 提供一个大型集群。我们假设集群的大小为50台机器,这在生产方案中是比较典型的。
- 大量的map进程在每台机器上运行。一个合理的假设是将会有和文件数量一样多的map进程。这个假设在后面的章节中将会放宽(当我们谈论压缩方案和替代文件格式如序列文件时),但目前为止我们先接受它。假设有1000万个文件,将有1000万个map进程启动。我们假设在某一时间有和CPU内核一样多的map进程在运行。对于一个双四核CPU机器,假设有8个Mapper同时运行,则每台机器负责运行200,000个map进程。因此,处理期间运行在每台机器上的8个Mapper共有25000次迭代(每次迭代每迭代运行8个Mapper,每个cpu核上一个)。
- 每个Mapper处理一个文件,提取词,并生成以下键/值对(www.askmac.cn):
- <the,1>
- <the,1>
- <test,1>
- 假设我们只有一个Reducer。当然,这还不是必要条件;它是默认设置。在实际情况下此默认值需要不断改变,但它适合于本例。
- Reducer接收以下格式的键/值对:<{WORD},[1,….1]>。也就是说,Reducer接收到的键/值对是这样的:键是一个从任意Mapper中输出的词(<WORD>,值是一个由任意Mapper为该词输出的值列表([1,….1])。Reducer输入键/值的例子:
- <the,[1,1,1,…,1]>
- <test,[1,1]>
- Reducer简单增加1,以提供{ WORD }的最终计数,并将结果以下列键/值对形式发送到输出:<{WORD},{COUNT OF WORD}>。Reducer输出的例子:
- <the,1000101>
- <test,2>
在reduce阶段接收键的值列表的键,是MapReduce中一个叫做sort/shuffle的阶段。Mapper发出的所有键/值对由Reducer中的键进行排序。如果分配多个Reducer,则每个Reducer分配一个键子集。对于给定Reducer,其键/值对由键进行排序,确保所有与键相关的值由Reducer一起接收。
- Note 注意 在每个键的reduce操作开始之前,reducer阶段实际上没有创建值列表。英语中典型的连接词占用太多内存。假设我们举例1000万个文档中,”the”一词出现了20次。我们将得到一个“the”的2亿列表1s。这将很容易压垮reducer的Java虚拟机(JVM)内存。相反,sort/shuffle阶段在reducer的一个本地文件系统中将“the”的1s累积在一起。当“the”一词的reducer操作启动时,1s只需通过Java迭代器接口流输出即可(www.askmac.cn)。
图2-2展示了刚才所述过程的逻辑流
图2-2 MapReduce计数应用程序
此时你可能在好奇:各Mapper是如何访问其文件的?文件存储在哪里?各Mapper是从网络文件系统( NFS )中获取的吗?并不是!还记得第1章中从网络读取是比从本地磁盘读取速度较慢的数量级。因此, Hadoop系统的设计是为了确保大多数Mapper从本地磁盘读取该文件。这意味着,我们例子中文档的整个语料库分布在50个节点上。然而, MapReduce系统参见一个统一的单一文件系统,虽然HDFS的整体设计使得每个文件能够感知网络交换,以确保任务被有效调度到磁盘本地进程中。这就是著名的Hadoop分布式文件系统( HDFS ),下面的章节中我们将会详细讨论HDFS(www.askmac.cn)。
Hadoop组件
本节我们将对Hadoop的各种组件进行深入探讨。我们以Hadoop 1.x组件开始,最后讨论新的2.x组件。在一个非常高的级别,Hadoop1.x拥有以下守护进程:
- NameNode: 维护每个存储在HDFS中文件的元数据。元数据包括关于包含文件及其在DataNodes上位置的块的信息。正如你很快就会看到,这是1.x的组件之一,却变成一个非常大的集群的瓶颈。
- Secondary NameNode: 这不是一个备份NameNode。事实上,它是Hadoop平台上一个名字取得不好的组件。它执行NameNode的一些日常功能。
- DataNode:将HDFS中实际的文件块存储在其自己的本地磁盘上。
- JobTracker: 主组件之一,负责管理任务的整体执行。它执行一些功能,如调度子任务(单个Mapper 和Reducer)到单个节点上,追踪每个任务和节点的健康状况,甚至重新调度失败的任务。不过,我们很快就会证明,如NameNode一样,当涉及到将Hadoop扩展到大型集群上时,Job Tracker变成一个瓶颈。
- TaskTracker: 运行在单个DataNode上,负责启动和管理单个Map/Reduce任务。与JobTracker通信(www.askmac.cn)。
Hadoop 1.x集群拥有两种类型的节点:主节点和从节点。主节点负责运行以下守护进程:
- NameNode
- Secondary NameNode
- JobTracker
从节点跨集群分布,且运行以下守护进程:
- DataNode
- TaskTracker
虽然在整个集群中,每个主守护进程只运行一个实例,还有多个DataNode和TaskTracker实例。在一个较小或开发/测试集群上,通常使三个主守护进程全都在同一台机器上运行。然而,对于生产系统或大型集群,让他们在不同的节点上运行更为稳妥。
Hadoop分布式文件系统(HDFS)
HDFS被设计用来支持那些使用较大文件的应用程序。这些应用程序将数据写入一次,并多次读取相同数据(www.askmac.cn)。
HDFS是下列守护进程协同工作的结果:
- NameNode
- Secondary NameNode
- DataNode
HDFS具有主/从结构。NameNode是主节点,DataNodes是从节点。通常情况下,DataNode守护程序在每个从节点上运行。它管理附属于每个DataNode的内存。HDFS公开了一个文件系统命名空间,允许数据被存储在节点的集群上,同时给用户提供一个对文件系统的单一系统视图。NameNode负责管理文件的元数据。
Hadoop文件分块存储的性质
首先,你应该了解文件是如何被物理存储在集群中的。在Hadoop中,每个文件被分成多个块。一个典型的块大小为64 MB,将块大小配置为32MB或128MB并不常见。HDFS中每个文件的块大小可配置。如果文件不是块大小的整数倍,则空间没有浪费,且最后的块小于总块大小。一个大型文件将被划分为多个块。
各个块存储在一个DataNode上。它也被复制以免出现故障。Hadoop中默认的复制因子为3。机架感知的Hadoop系统将一个块存储在本地机架的一个节点上(假设Hadoop客户端正在其中的一个DataNodes上运行;否则,机架随机选择)。第二个副本位于一个不同的远程机架的一个节点上,且最后一个节点位于相同远程机架的一个节点上。Hadoop系统通过从单独网络拓扑文件中的节点域名系统(DNS)名称映射中的配置作出机架感知,其路径通过Hadoop配置文件被引用(www.askmac.cn)。
- 注意 有些Hadoop系统可将复制因子减少为2。一个例子是运行在eMCIsilon 硬件上的Hadoop。基本原理是该硬件使用raId 5,提供了一个内置冗余,使得复制因子变小。减少复制因子明显有好处,因为它提高了I / O性能(少写1个副本)。下面的白皮书展示了这种系统的设计:
www.emc.com/collateral/software/white-papers/h10528-wp-hadoop-on-isilon.pdf
为什么不将三个副本全都放在不同的机架上?毕竟,它只会增加冗余。这将进一步避免机架故障,和提高机架吞吐量。然而,相比较节点故障,机架故障的可能性要小得多,试图将副本保存到多个机架只会降低写入性能。因此,一个折衷的方法是将两个副本保存在同一远程机架的节点上,以换取更好的性能。这种被性能约束驱动的巧妙的设计决策在Hadoop系统中是很常见的(www.askmac.cn)。
文件元数据和NameNode
当客户端请求一个文件或决定将一个文件存储在HDFS中时,它需要知道要访问哪个DataNodes。根据此信息,客户端可直接通过独立的DataNodes写入。NameNode负责维护这些元数据。
NameNode公开了一个文件系统命名空间,允许数据存储在节点的集群上,同时给用户提供一个对文件系统的单一系统视图。HDFS公开了一个对文件系统的层次结构视图,其中文件存储在目录中,目录可以嵌套。NameNode负责管理文件和目录的元数据。
NameNode管理所有操作,如文件/目录打开、关闭、重命名、移动等等。DataNodes负责服务于实际文件数据。这是一个很重要的区别!当一个客户端请求或发送数据时,数据不会物理经过NameNode。这将是一个很大的瓶颈。相反,客户端仅仅从NameNode中获得文件的元数据,并直接从节点获取文件块。
一些由NameNode存储的元数据包括:
- 文件/目录名称及其相对于父目录的位置。
- 文件和目录所有者和权限。
- 单个块的文件名。每个块被作为一个文件存储在DataNode的本地文件系统,由Hadoop系统管理员进行配置的目录中(www.askmac.cn)。
应当指出的是,NameNode不存储每个块的位置(DataNode标识)。该信息是在集群启动时从各个DataNodes获得的。NameNode只维护关于哪些块(DataNode上各块的文件名)构成HDFS中的文件的信息。
元数据存储在磁盘上,但在集群操作过程中被加载到内存,以便于快速访问。这是Hadoop能快速运行的关键,但也导致了它的一个主要瓶颈,并促使Hadoop 2.x的问世。
元数据的每一项消耗大约200字节的RAM。考虑一个1 GB的文件和64 MB的块大小。这种文件需要16×3(含副本)=48个块存储。现在考虑每1 MB 1000个文件。该文件系统需要1000×3 = 3000个块存储。(每个块只有1 MB大,且多个文件不能存储在一个块中)。因此,元数据的量显著增加。这将导致NameNode上更多的内存占用。这个例子也有助于解释为什么Hadoop系统倾向于大文件胜过小文件。大量的小文件只会压垮NameNode。
包含元数据的NameNode文件是fsimage。系统运行期间元数据的任何变化都存储在内存中,并保存到另一个叫做edits的文件中。Secondary NameNode定期将edits文件与fsimage文件合并起来。(我们讨论Secondary NameNode时会详细讨论该过程)。这些文件不包含实际数据;实际数据被存储在,运行DataNode守护程序的从节点的各个块上。如前面提到的,这些块仅仅是从节点上的文件。块只存储原始内容,不存储元数据。因此,丢失了NameNode元数据将使整个系统无法使用。NameNode元数据使用户能够弄清从节点上原始存储的块。
DataNode守护进程定期发送心跳消息到NameNode。这使得NameNode对每个DataNode的健康状况保持了解,且不将任何用户请求传递到故障节点(www.askmac.cn)。
HDFS 写的机械原理
一个HDFS写操作涉及到文件的创建。从用户的角度来看,HDFS不支持文件更新。(这不完全是正确的,因为为了HBase的目的,文件附加特性对于HDFS是可用的。但不建议用于一般用途的客户端使用。)为以下讨论的目的,我们假定默认复制因子为3。
Figure 2-3 depicts the HDFS write process in a diagram form, which is easier to take in at a glance.
图2-3以图的形式描绘了HDFS 的写入过程,更加一目了然。
图2-3 HDFS写入过程
以下步骤允许客户端将一个文件写入HDFS:
- 客户端开始将文件内容流化到其本地文件系统中的临时文件上。该步骤是在接触NameNode之前完成(www.askmac.cn)。
- 当文件数据大小达到块的大小时,客户端接触NameNode。
- 现在NameNode在HDFS文件系统层次结构中创建了一个文件,并通知客户端有关DataNodes的块标识符和位置。DataNodes列表也包含复制节点列表。
- 客户端使用前面步骤中的信息将临时文件刷新到从NameNode接收的一个数据块位置(第一个DataNode)上,导致在DataNode的本地存储上创建了一个实际文件。
- 当文件(客户端所看到的HDFS文件)关闭后,NameNode提交该文件,使其在系统中变得可见。如果在提交发出之前NameNode关闭,则文件会丢失。
第4步值得额外关注。该步骤中的刷新过程操作如下:
- 第一个DataNode从较小数据包(通常大小为4 KB)的客户端接收数据。虽然该部分正被写入第一个DataNode的磁盘上,它开始将其流到第二个DataNode上。
- 第二个DataNode开始将流数据块写入到它自己的磁盘,同时开始将数据块的数据包流至第三个DataNode。
- 现在第三个DataNode将数据写入其自己的磁盘。因此,数据被写入,并通过DataNode以管道方式被复制。
- 从每个DataNode将确认包发送回管道中的前一个。第一个DataNode最终发送确认给客户端节点。
- 当客户端接收到一个数据块的确认,则假设该块保存到所有节点,并且发送最终确认给NameNode。
- 如果管道中的任何DataNode发生故障,则关闭管道。数据仍被写入到剩余的DataNodes上。NameNode意识到该文件正被复制,并采取措施重新复制一个好DataNode上的数据,以确保足够的复制水平。
- 还计算每个块的校验码,并将其用于验证块的完整性。这些校验码存储在HDFS中的单独隐藏文件中,并在当它被读取时用于验证块数据的完整性(www.askmac.cn)。
HDFS 读的机械原理
现在我们将讨论文件是如何被从HDFS中读取的。HDFS读过程如图2-4所示:
图2-4 HDFS读取过程
客户端可通过以下步骤读取文件:
- 客户端接触返回块列表及其位置(包括副本位置)的NameNode。
- 客户端直接通过接触DataNode开始读取块。如果DataNode失败,客户端接触托管副本的DataNode。
- 随着块被读出,计算校验码并与文件写入时计算的校验码进行比较。如果校验失败,则块被从副本中检索出(www.askmac.cn)。
HDFS 删除的机械原理
要从HDFS中删除文件,遵循以下步骤:
- NameNode仅仅重命名文件路径来表示文件被移动到/ trash目录。注意,唯一发生在这里的操作就是与重命名文件路径与关的元数据更新操作。这是一个非常快的过程。该文件在/ trash目录中停留了预定义的一段时间间隔(当前设置为6小时,它目前是不可配置的)。在此期间,通过从/ trash目录移动它很容易可以恢复该文件。
- 一旦该文件应保持在/ trash目录中的时间间隔期满后,NameNode会从HDFS命名空间中删除文件。
- 构成被删除文件的块被释放,系统的可用空间增加。
文件的复制因子不是一成不变的。它可以减少。该信息通过下一个心跳消息被传递到NameNode。然后DataNode主动从其本地存储器中移除块,使得集群的可用空间增多。因此,NameNode积极维护每个文件的复制因子。
确保HDFS可靠性
Hadoop和HDFS被设计成故障容错。数据损失可以发生在两个方面:
- DataNodes可能发生故障:每个DataNode定期发送心跳消息到NameNode(默认为3秒)。如果NameNode没有在一个预定义的时间间隔内收到心跳消息,则假设DataNode故障。此时,它积极启动存储在遗失节点(从其副本之一获得)上的复制块到一个健康的节点上,主动维修复制因子。
- 由于一种称为位衰减(bit rot)的现象,数据可能会损坏:这是指代表一个“位”的小电荷分散,导致数据丢失的事件。这种情况只有在HDFS读操作过程中由于“校验”不匹配才能被检测到。如果该块的校验和不匹配,再复制就会被启动,因为块被认为已损坏,NameNode积极尝试恢复该块的复制因子(www.askmac.cn)。
Secondary NameNode
我们现在准备讨论Secondary NameNode的作用。该组件可能是Hadoop平台中最名不副实的组成部分。Secondary NameNode不是一个故障转移节点。
你刚才了解到NameNode将其所有元数据保存在内存中。它首先从存储在NameNode本地文件系统中的fsimage文件中读取。在Hadoop系统操作期间, NameNode内容的更新被应用到内存中。然而,为了避免数据丢失,这些编辑也被应用到一个名为edits的本地文件中。
- 注意 fsimage文件实际上并不存储块的位置。它在系统启动期间从数据节点获取每个数据节点的信息,并将其保存在内存中。
edits文件的目的是收集系统操作期间的变化。如果系统重新启动,edits文件的内容可在重启过程中被整合到fsimage中。不过这会减缓Hadoop重启的速度。Secondary NameNode的创建正是为了处理这一问题(www.askmac.cn)。
Secondary NameNode的作用是定期合并fsimage文件中edits文件的内容。为此,Secondary NameNode定期执行以下步骤序列:
- 它要求主节点转存edits文件,这确保了新的编辑去到一个新的文件。这个新的文件被称为edits.new。
- Secondary NameNode向主节点请求fsimage文件和edits文件。
- Secondary NameNode将fsimage文件和edits文件合并到一个新的fsimage文件中。
- NameNode从 Secondary NameNode接收新的fsimage文件 ,现在edits文件被第一步中创建的edits.new文件的内容代替。
- 当检查点操作发生时,fstime 文件被更新到记录中。
现在应该清楚为什么NameNode是Hadoop1.x中的单点故障。如果fsimage和edits文件受到损坏,则HDFS系统中的所有数据都将丢失。因此,尽管DataNode仅仅是一个JBOD商品机器(意为“简单磁盘捆绑” ), NameNode和Secondary NameNode必须连接到更可靠的存储器(基于RAID),以防止数据丢失。前面提到的两个文件还必须定期备份。如果他们需要在备份中恢复,从现在到进行备份之间的所有更新都将丢失。表2-1总结了启用NameNode支持HDFS的关键文件(www.askmac.cn)。
表2-1 关键的NameNode文件
文件名 描述
fsimage 包含上一次检查点之前HDFS元数据的持久化状态
edits 包含自上一次检查点之后HDFS元数据的状态变化
fstime 包含上一次检查点的时间戳
TaskTracker
运行在Hadoop集群各计算节点上的TaskTracker守护进程,接收单个任务如Map, Reduce和Shuffle操作的请求。每个TaskTracker配置有一组通常被设置为机器上可用内核总数的插槽。当收到请求(从JobTracker)启动任务时,TaskTracker启动该任务的一个新JVM。JVM重用是可能的,但该功能实际使用的例子却很少见。Hadoop平台的大多数用户关闭该功能。TaskTracker被分配一个任务,取决于它有多少空闲的插槽(任务总数=实际运行的任务)。TaskTracker负责发送心跳信息给JobTracker。除了告诉JobTracker它是健康的,这些消息还告诉JobTracker有关可用空闲插槽的数量(www.askmac.cn)。
JobTracker
JobTracker守护进程负责启动和监测MapReduce任务。当客户端提交一个任务到Hadoop系统,图2-5中所示的步骤序列启动。
图2-5 任务提交过程
该过程又详细分为以下步骤:
- 由Job Tracker接收任务请求。
- 大多数MapReduce任务需要一个或多个输入目录。Job Tracker向NameNode请求一个包含在输入目录列表中文件的块的DataNode列表。
- 现在JobTracker计划任务执行。在该步骤中,JobTracker确定执行任务所需的任务数(Map任务和Reduce任务)。它还尝试调度尽可能靠近数据块的任务。
- JobTracker提交任务到每个TaskTracker节点用于执行。监测TaskTracker节点的健康状况。他们在预定的时间间隔发送心跳信息到JobTracker节点。如果在预定的时间段内没有收到心跳消息,则TaskTracker节点被视为已失败,任务被重新调度到一个单独节点上运行。
- 一旦所有的任务完成,JobTracker将该任务的状态更新为成功。如果一定数目的任务多次失败(具体数字通过Hadoop配置文件中的配置指定),则JobTracker宣布该任务失败。
- 客户端轮询JobTracker以更新任务进度。
到目前为止,有关Hadoop 1.x组件的讨论应该已经明确: JobTracker也只是一个单点故障。如果JobTracker关闭,则运行任务的整个集群也会如此。此外,只有一个JobTracker,增加了多个任务同时运行环境下单个JobTracker的负载(www.askmac.cn)。
Hadoop 2.0
MapReduce已经发生了彻底的改革。其结果就是Hadoop 2.0,有时被称为MapReduce 2.1(MR V2)或YARN。本书会经常引用版本2.X,因为改良版本预计不会有任何根本上的行为和结构变化。
MR v2是与MR V1兼容的应用程序编程接口(API),只有一个重新编译步骤。但其基本架构已被彻底改变。在Hadoop 1.x中,JobScheduler有两大功能:
- 资源管理
- 任务调度/任务监控
YARN旨在将这些功能分离到不同的守护进程。其想法是有一个全局的资源管理器和每个应用程序的主应用程序。注意,我们提到的是应用程序,而不是作业。在新的Hadoop 2.x中,一个应用程序可以是典型MapReduce任务中的单个作业,也可以是作业的一个有向非循环图(DAG)。DAG是一个曲线图,其节点相连,使得无周期成为可能。也就是说,无论你如何遍历一个图形,在遍历的过程中你不能重复到达一个节点。坦白地说,任务的一个DAG是指相互之间有层次关系的作业。
YARN还旨在扩大Hadoop在MapReduce以外的工具。下一章我们将发掘MapReduce框架的各种限制。较新的框架已经发展到能够解决这些限制。例如,Apache Hive的出现在Hadoop之上新添了SQL功能,Apache PIG解决了基于脚本的、数据流式的处理。即使较新的框架,如Apache HAMA,解决迭代计算,这在机器学习风格用例中是非常典型的(www.askmac.cn)。
来自Berkley的Spark/Shark框架是Hive和HAMA之间的一个交叉,提供低延迟的SQL访问和一些内存计算。虽然这些框架都被设计用于HDFS之上,但并不全都是Hadoop框架中的一等公民。我们需要的是一个总体框架,使不同计算原理的新框架(不仅仅是MapReduce的模型),如HAMA基于的批量同步并行(BSP)模型或Shark/Spark基于的in-memory缓存和计算模型,都被合并到Hadoop框架中。
新框架设计应完全支持新型的应用程序,同时还在整个Hadoop系统内运行。这将使有关安全和资源管理的全系统的政策都能一致地应用,即使所有系统共享相同的底层HDFS 。
YARN系统具有以下部件:
- 全局资源管理器
- 节点管理器
- 特定应用的主应用程序
- 调度器
- 容器
一个容器包括一个CPU内核总数和主内存大小的子集。应用程序将在容器集中运行。一个主应用程序实例向全局资源管理器请求资源。调度器通过每个节点的节点管理器分配资源(容器)。然后节点管理器将各个容器的使用情况汇报到资源管理器(www.askmac.cn)。
全局资源管理器和每个节点的节点管理器构成了新的MapReduce框架的管理体制。资源管理器是资源分配的最终权威。每个应用程序类型都有一个主应用程序。(例如,MapReduce是一种类型,每个MapReduce任务是MapReduce类型的一个实例,类似于面向对象编程中类和对象的关系)。应用程序类型的每个应用程序都是一个主应用程序被实例化的实例。主应用程序实例与容器的资源管理器协商以执行作业。资源管理器利用调度器(全局组件)与每个节点的节点管理器协同合作来分配这些资源。从系统的角度看,主应用程序也在容器中运行。
YARN的整体架构如图2-6所示。
图2-6 YARN架构
MapReduce V1框架被重用,且无任何大的改动,使其向后兼容于现有的MapReduce程序。
YARN组件
我们来详细讨论每个组件。在一个较高级别上,我们有一堆商品机安装在Hadoop集群上。每台机器称为一个节点。
容器
容器是在YARN框架中的一个计算单元。它是一个工作发生单元的子系统。或者,在MapReduce v1语言中,它是相当于一个在其中执行任务的组件。容器和节点之间的关系是:
一个节点可以运行几个容器,但一个容器不能跨越节点边界。
容器是一组被分配的系统资源。目前只支持两种类型的系统资源(www.askmac.cn)。
- CPU核心
- 以MB为单位的内存
容器包括资源将在某个节点上执行,因此容器中的隐式是“资源名称”,即机架和容器运行的节点名称的概念。请求一个容器,就是在一个特定节点上请求。因此,容器就是赋予一个应用程序的在一个特定主机上使用特定数目的CPU内核和特定容量的内存的权利。
任何任务或应用程序(单个任务或任务的DAG)基本上都在一个或多个容器中运行。最终负责物理分配容器的YARN框架实体被称为节点管理器。
Node Manager
节点管理器运行在集群中的单个节点上,集群中的每个节点运行自己的节点管理器。它是一个从属服务:收到来自另一个称为资源管理器的组件的请求,分配容器到应用程序。它也负责监测和报告资源管理器的使用量度。节点管理器连同资源管理器构成Hadoop集群上负责管理资源分配的框架。资源管理器是一个全局性的部件,而节点管理器是负责管理Hadoop集群上各节点健康状况的每个节点的代理。节点管理器的任务包括以下:
- 接收来自资源管理器的请求,并为任务分配容器。
- 和资源管理器交换信息,以确保整个集群的顺利运行。资源管理器基于从每个节点管理器接收到的报告追踪全局的健康状况,并授权节点管理器监控和管理其自己的健康状况。
- 管理每个启动容器的生命周期。
- 每个节点上的日志管理。
- 执行被各种YARN应用程序利用的辅助服务。例如,为当前Hadoop实现中实现MapReduce的Shuffle服务。
当一个节点启动时,它向资源管理器注册,并告知资源管理器有多少资源(最终被分配以形成容器)是可用的。在运行时,随着节点管理器和资源管理器协同工作以确保集群功能完备并得到最佳利用,该信息是不断更新的(www.askmac.cn)。
节点管理器只负责管理容器的抽象符号;它不包含任何有关各应用程序或应用程序类型的知识。这一责任被委托给一个叫做主应用程序的部件。但在我们讨论主应用程序之前,首先来简单了解一下资源管理器。
Resource Manager
资源管理器主要是调度器:它在相互竞争的应用程序中仲裁资源,以确保集群的最佳利用。资源管理器中有一个可插拔的调度器,负责给各个运行中的应用程序分配资源,但受常见的能力和队列限制。调度的例子包括Hadoop中的Capacity Scheduler和Fair Scheduler,这两个你在后面的章节中都会遇到。
创建、配置和监控资源的实际任务被委派给每个节点的节点管理器。这种关注点的分离使资源管理器的扩展规模远远超过传统的JobSchedule(www.askmac.cn)r。
Application Master
Application Master是旧MapReduce V1框架和YARN之间的关键区别。Application Master是特定框架库的一个实例。它从资源管理器协商资源,与节点管理器协同工作来获取那些资源和执行其任务。Application Master是从资源管理器协商资源容器的组件。
Application Master带给YARN框架的主要好处有:
- 提高了可扩展性
- 一个更加通用的框架
在MapReduce v1中,JobTracker负责管理任务故障转移,还负责为任务分配资源。v2中可扩展性提高,因为资源管理器(代替了JobTracker)现在只负责调度。管理任务或应用程序的任务属于Application Master。如果任务失败,Application Master将从资源管理器协商资源,并尝试重新执行任务。
在MapReduce v1中,Hadoop框架仅支持MapReduce类型的任务;它不是一个通用框架。主要原因是关键部件如JobTracker和TaskTracker是用深深扎根于其设计的Map和Reduce任务的概念开发的。随着MapReduce得到更多人的关注,人们发现使用MapReduce的某些类型的计算并不实用。所以新的框架,如Apache HAMA和Apache Giraph基于的BSP框架,被开发出来。它们擅长图形计算,在HDFS上也运转良好。在撰写本文时,in-memory框架,如Shark/Spark,也正引起大家的关注。虽然它们在HDFS上也运转良好,却不适合于Hadoop 1.x,因为他们使用的是不同计算理念设计的。
v2中的Application Master方法作为YARN的一部分改变了这一切。将个性化设计理念应用到Application Master,使几个框架得以在一个管理系统中共存。因此,过去Hadoop/ HAMA / Shark在Hadoop 1.x同一HDFS的不同管理系统上运行,导致无法预料的系统和资源冲突,他们现在可以在同一Hadoop 2.x系统上运行。他们全都从资源管理器仲裁资源。YARN将使Hadoop系统变得越来越普遍。现在Hadoop不仅仅只支持MapReduce类型的计算,且变得更可插拔:如果发现新系统用某种类型的计算工作得更好,可开发他们的Application Master并插入到Hadoop系统中。现在Application Master概念允许Hadoop扩展到MapReduce之外,使MapReduce能够与其他框架共存、合作(www.askmac.cn)。
YARN请求的剖析
当用户提交一个任务到Hadoop 2.x框架,底层YARN框架处理该请求(见图2-7)。
图2-7 Application master 启动
以下是所使用的步骤:
- 客户端程序提交应用。应用程序类型依次决定被指定的Application Maste
- 资源管理器协商资源获取节点上的一个容器以启动Application Master的一个实例(www.askmac.cn)。
- Application Master向资源管理器注册。该注册使客户端能够向资源管理器查询与Application Master有关的细节。因此,客户端将通过自身的资源管理器与已启动的Application Master进行通信。
- 在操作过程中,Application Master通过资源请求从资源管理器协商资源。其中资源请求包含容器被请求的节点和容器(CPU代码和内存规格)。
- 在启动容器内执行应用程序代码,并通过一个特定应用协议,将其进展报告给Application Master(可能是远程)。
- 客户端程序通过特定应用协议与Application Master进行通信。客户端通过查询其在步骤3中注册的资源管理器关联Application Master。
以上步骤如图2-8所示。
图2-8 任务资源分配和执行
一旦应用程序完成执行,Application Master取消在资源管理器上的注册,所使用的容器被释放回系统。
HDFS高可用性
HDFS之前的讨论明确表示,在Hadoop 1.x中,NameNode是一个单点故障。Hadoop1.x系统只有一个NameNode,如果承载NameNode服务的机器不可用,则整个集群不可访问,除非NameNode在另一台机器上重新启动。除了偶然的NameNode损耗,从维护的角度看也存在限制。如果运行NameNode的节点需要重新启动,则在NameNode不运行期间整个集群都将不可用(www.askmac.cn)。
Hadoop 2.x介绍了一种高可用性NameNode概念,这里只从概念的角度讨论。可以咨询Hadoop网站了解有关如何实现高可用性NameNode的发展细节。
高可用性NameNode背后的核心理念是,使用两个类似的NameNode:一个是活动模式,另一个是待机模式。活动节点支持系统中的客户端;备用节点需要与活动NameNode数据同步,以便进行快速的故障转移操作。当前的设计是,两个NameNode必须共享一个存储装置(通过一个NFS)。对活动NameNode空间的任何更改都被应用到共享存储设备的edits日志文件中。备用节点不断将这些变更应用于自己的命名空间。一旦出现故障,备用节点首先确保所有的编辑都被应用,并接管活动NameNode的责任。
记住,NameNode不包含有关块位置的元数据;它是启动期间由NameNode从DataNode获得的。为确保备用NameNode能够快速启动,DataNode知道两个NameNode的位置,并在启动时向他们发送该信息。同时与两个NameNode交换心跳消息。
小结
本章介绍了Hadoop系统的各种概念。以一个规范化的字数统计例子开始,接着探讨了Hadoop的各种关键功能。你应该了解了Hadoop分布式文件系统(HDFS),并看到了在Hadoop1.x中是如何使用JobTracker和TaskTracker守护进程来管理任务的。使用有关这些守护程序限制可扩展性方式的知识,我们又向你介绍了YARN,Hadoop 2.X中能够解决这些限制的功能。然后探讨了高可用性的NameNode。
下一章将探讨Hadoop软件的安装,你将会编写和执行你的第一个MapReduce程序。
Comment