HADOOP2
Hadoop是Apache软件基金会旗下的一个分布式系统基础架构。Hadoop2的框架最核心的设计就是HDFS,MapReduce,YARN。为海量的数据提供了存储和计算。
HDFS 用于海量数据的存储
MapReduce 用于分布式计算
YARN 是hadoop2中的资源管理系统
区别: hadoop1仅由HDFS和MapReduce组成,MapReduce是hadoop1中唯一的计算框架。而hadoop2多了一个YARN,是hadoop2中的资源管理系统,它的出现使得hadoop2相对于hadoop1,可以能够运行更多的计算框架。
1. YARN
通过YARN实现资源的调度与管理,从而使Hadoop 2.0可以运行更多种类的计算框架,如Spark等;
2. NameNode HA
实现了NameNode的HA方案,即同时有2个NameNode(一个Active另一个Standby),如果ActiveNameNode挂掉的话,另一个NameNode会转入Active状态提供服务,保证了整个集群的高可用;
3. HDFS federation
实现了HDFS federation,由于元数据放在NameNode的内存当中,内存限制了整个集群的规模,通过HDFS federation使多个NameNode组成一个联邦共同管理DataNode,这样就可以扩大集群规模;
4. Hadoop RPC序列化扩展性
Hadoop RPC序列化扩展性好,通过将数据类型模块从RPC中独立出来,成为一个独立的可插拔模块。
HDFS原理
HDFS是一个分布式文件系统,具有高容错的特点。它可以部署在廉价的通用硬件上,提供高吞吐率的数据访问,适合那些需要处理海量数据集的应用程序。
1.
支持超大文件;
2. 检测和快速应对硬件故障;
3. 流式数据访问;
4. 简化一致性模型;
1.
低延迟数据访问;
2. 大量的小文件;
3. 多用户写入文件,修改文件;
1.NameNode上保存着HDFS的名字空间,对于任何文件系统元数据产生修改的操作都会作用于NameNode上。
2.DataNode将HDFS数据以文件的形式存储在本地的文件系统中,它并不知道有关HDFS文件的信息,它把每个HDFS数据块存储在本地文件系统的一个单独的文件中。
HDFS也有块的概念,hadoop2中HDFS块默认大小为128MB。以Linux上以普通文件的形式保存在数据节点的文件系统中,数据块是HDFS的文件存储处理的单元。
1.HDFS可以保存比存储节点单一磁盘量大的文件
2.简化了存储系统,简化了存储管理,也消除了分布式管理文件元数据的复杂性
3.方便容错,有利于数据复制
HDFS读写流程
a) 客户端(client)用FileSystem的open()函数打开文件
b) DistributedFileSystem用RPC调用元数据节点,得到文件的数据块信息。
c) 对于每一个数据块,元数据节点返回保存数据块的数据节点的地址。
d) DistributedFileSystem返回FSDataInputStream给客户端,用来读取数据。
e) 客户端调用stream的read()函数开始读取数据。
f) DFSInputStream连接保存此文件第一个数据块的最近的数据节点。
g) Data从数据节点读到客户端(client) 当此数据块读取完毕时,DFSInputStream关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。
h) 当客户端读取完毕数据的时候,调用FSDataInputStream的close函数。
i) 在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。 失败的数据节点将被记录,以后不再连接。
a) 客户端调用create()来创建文件
b) DistributedFileSystem用RPC调用元数据节点,在文件系统的命名空间中创建一个新的文件。
c) 元数据节点首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件。
d) DistributedFileSystem返回DFSOutputStream,客户端用于写数据。
f) 客户端开始写入数据,DFSOutputStream将数据分成块,写入data queue。
g) Data queue由Data Streamer读取,并通知元数据节点分配数据节点,用来存储数据块(每块默认复制3块)。分配的数据节点放在一个pipeline里。
h) Data Streamer将数据块写入pipeline中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。
i) DFSOutputStream为发出去的数据块保存了ack queue,等待pipeline中的数据节点告知数据已经写入成功。 如果数据节点在写入的过程中失败:
关闭pipeline,将ack queue中的数据块放入data queue的开始。
当前的数据块在已经写入的数据节点中被元数据节点赋予新的标示,则错误节点重启后能够察觉其数据块是过时的,会被删除。
失败的数据节点从pipeline中移除,另外的数据块则写入pipeline中的另外两个数据节点。
元数据节点则被通知此数据块是复制块数不足,将来会再创建第三份备份。
j) 当客户端结束写入数据,则调用stream的close函数。此操作将所有的数据块写入pipeline中的数据节点,并等待ack queue返回成功。最后通知元数据节点写入完毕。
YARN原理介绍与基本架构
Hadoop1.x中MapReduce弊端
1.
扩展性差
2.
可靠性差
3.
资源利用率低
4.
无法支持多种计算框架
YARN是一种Hadoop资源管理器,它是一个通用资源管理系统。可以为上层应用提供统一的资源管理和调度。它的引入为集群在利用率,资源统一管理和数据共享等方面带来了巨大的好处。
通用的统一的资源管理系统:
1.
长应用程序;如HBse,HTTPServer
2.
短应用程序;如MapReduce,Spark
它是一个全局的资源管理器,负责整个系统的资源管理和分配,主要由调度器和应用程序管理器两个组件构成。
2.
Application Master
用户提交的每个应用程序均包含1个ApplicationMaster,主要功能包括与ResourceManager调度器协商以获取资源、将得到的任务进一步分配给内部的任务、与NodeManager通信以启动/停止任务、监控所有任务运行状态并在任务运行失败时重新为任务申请资源以重启任务等。
3.
Node Manager
它是每个节点上的资源和任务管理器,它不仅定时向ResourceManager汇报本节点上的资源使用情况和各个Container的运行状态,还接收并处理来自ApplicationMaster的Container启动/停止等各种请求。
4.
Container
它是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当ApplicationMaster向ResourceManager申请资源时,返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。
MapReduce原理
MapReduce最早是由Google公司研究提出的一种面向大规模数据处理的并行计算模型和方法,是hadoop面向大数据并行处理的计算模型,框架和平台。
整体图
MapReduce的map端输出作为输入传递给reduce端,并按键排序的过程称为shuffle。
map 端
map函数开始产生输出时,并不是简单地将它输出到磁盘。这个过程更复杂,利用缓冲的方式写到内存,并出于效率的考虑进行预排序。shuffle原理图就看出来。
每个map任务都有一个环形内存缓冲区,用于存储任务的输出。默认情况是100MB,可以通过io.sort.mb属性调整。一旦缓冲内容达到阀值(io.sort.spill.percent,默认0.80,或者80%),一个后台线程开始把内容写到磁盘中。在写磁盘过程中,map输出继续被写到缓冲区,但如果在此期间缓冲区被填满,map会阻塞直到写磁盘过程完成。在写磁盘之前,线程首先根据数据最终要传送到reducer把数据划分成相应的分区,在每个分区中,后台线程按键进行内排序,如果有一个combiner,它会在排序后的输出上运行。
reducer通过HTTP方式得到输出文件的分区。用于文件分区的工作线程的数量由任务的tracker.http.threads属性控制,此设置针对每个tasktracker,而不是针对每个map任务槽。默认值是40,在运行大型作业的大型集群上,此值可以根据需要调整。
reducer端
map端输出文件位于运行map任务的tasktracker的本地磁盘,现在,tasktracker需要为分区文件运行reduce任务。更进一步,reduce任务需要集群上若干个map任务完成,reduce任务就开始复制其输出。这就是reduce任务的复制阶段。reduce任务有少量复制线程,所以能并行取得map输出。默认值是5个线程,可以通过设置mapred.reduce.parallel.copies属性改变。
如果map输出相当小,则会被复制到reduce tasktracker的内存(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制),否则,map输出被复制到磁盘。一旦内存缓冲区达到阀值大小(由mapred.job.shuffle.merge.percent决定)或达到map输出阀值(mapred.inmem.merge.threshold控制),则合并后溢出写到磁盘中。
随着磁盘上副本的增多,后台线程会将它们合并为更大的、排好序的文件。这会为后面的合并节省一些时间。注意,为了合并,压缩的map输出都必须在内存中被解压缩。
复制完所有map输出被复制期间,reduce任务进入排序阶段(sort phase 更恰当的说法是合并阶段,因为排序是在map端进行的),这个阶段将合并map输出,维持其顺序排序。这是循环进行的。比如,如果有50个map输出,而合并因子是10 (10默认值设置,由io.sort.factor属性设置,与map的合并类似),合并将进行5趟。每趟将10个文件合并成一个文件,因此最后有5个中间文件。
在最后阶段,即reduce阶段,直接把数据输入reduce函数,从而省略了一次磁盘往返行程,并没有将5个文件合并成一个已排序的文件作为最后一趟。最后的合并既可来自内存和磁盘片段。
在reduce阶段,对已排序输出中的每个键都要调用reduce函数。此阶段的输出直接写到输出文件系统中。
reducer如何知道要从那个tasktracker取得map输出呢?
map任务成功完成之后,它们通知其父tasktracker状态已更新,然后tasktracker通知jobtracker。这些通知都是通过心跳机制传输的。因此,对于指定作业,jobtracker知道map输出和tasktracker之间的映射关系。reduce中的一个线程定期询问jobtracker以便获得map输出的位置,直到它获得所有输出位置。 由于reducer可能失败,因此tasktracker并没有在第一个reducer检索到map输出时就立即从磁盘上删除它们。相反,tasktracker会等待,直到jobtracker告知它可以删除map输出,这是作业完成后执行的。