HDFS 分布式文件系统
Hadoop -YARN
Hadoop -MapReduce
导读
1.HDFS是什么
2.HDFS架构及组件功能介绍
3.读写流程
HDFS是什么
HDFS,是Hadoop Distributed File System
的简称,是被设计成适合运行在通用硬件上的分布式文件系统。HDFS是一个高度容错性的系统,适合部署在廉价的机器上,支持动态扩容。HDFS能提供高吞吐量的数据访问,适合大规模数据集上的应用。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。
注意: HDFS 是设计成适应一次写入,多次读出的场景
HDFS架构及组件介绍
HDFS分布式文件系统是一个块结构的文件系统,其中每个文件被分成预先确定大小的块。这些块存储在一个由一台或多台机器组成的集群中。Apache Hadoop HDFS体系结构遵循主/从体系结构,其中集群由单个NameNode(主节点)组成,其他所有节点都是DataNode(从节点)。HDFS可以部署在支持Java的各种机器上。虽然可以在一台机器上运行多个数据节点,但在现实世界中,这些数据节点分布在不同的机器上。
NameNode
NameNode是
Hadoop-HDFS
体系结构中的主节点,用于维护和管理dataNode(从节点)上的block。nameNode是一个高可用的服务器,它管理文件系统命名空间并控制client对文件的访问。HDFS架构的构建方式使数据不会存储在nameNode上。数据只存储在dataNode上。
NameNode的功能:
维护和管理数据节点(从节点<DataNode>)的主守护进程,记录集群中存储的所有文件的元数据,如block的位置、文件的大小、权限、层次结构等
有两个文件与元数据关联:
FsImage
:是nameNode中关于元数据的镜像,一般称为检查点。
一般开始时对nameNode的操作都放在edits中,为什么不放在FsImage中呢?
因为FsImage是nameNode的完整的镜像,内容很大,如果每次都加载到内存的话生成树状拓扑结构,这是非常耗内存和CPU。FsImage内容包含了nameNode管理下的所有dataNode中文件及文件block及block所在的dataNode的元数据信息。随着EditLogs内容增大,就需要在一定时间点和fsimage合并。
EditLogs
:client对hdfs进行写文件时会首先被记录在EditLogs文件中。EditLogs修改时元数据也会更新。每次hdfs更新时EditLogs先更新后client才会看到最新信息。
1.记录对文件系统元数据所做的每个更改。例如,如果在HDFS中删除了一个文件,NameNode会立即将其记录在EditLog中。
2.定期从集群接收所有dataNode的心跳和block报告,以确保dataNode处于活跃专状态。
3.记录了HDFS中的所有block以及这些block所在的节点。
4.NameNode还负责处理所有块的副本(replicas),后面会详细讨论
5.当dataNode发生故障时,NameNode为新的副本(replicas)选择新的dataNode,平衡磁盘使用并管理到dataNode的通信流量。
DataNode
dataNode是HDFS中的从节点。与nameNode不同,dataNode是一种普通硬件,也就是说,它是一种质量不高或可用性不高的廉价系统。DataNode是一个block服务器,它将数据存储在本地文件ext3或ext4中。
dataNode的功能:
1.是每个从节点上运行的从守护进程或进程。
2.实际数据存储在dataNode上。
3.dataNode执行来自文件系统client的low-level读写请求。
4.它们定期向NameNode发送心跳信号以报告HDFS的总体运行状况,默认情况下,此频率设置为3秒。
SecondaryNameNode
除了这NameNode和DataNode进程之外,还有第三个进程为SecondaryNameNode的进程。secondaryNameNode作为辅助进程与NameNode同时工作,
SecondaryNameNode节点并不是NameNode备份节点,只用于辅助NameNode进行工作
SecondaryNameNode的功能:
1.secondaryNameNode持续的从nameNode的RAM中读取所有文件系统和元数据并将其写入本地文件系统或NFS,着备份的过程是同步的,并具有原子性。
2.定期将nameNode的EditLogs和FsImage进行合并(combining).避免EditLog过大,通过创建检查点checkpoint来合并,并会维护合并后的FsImage副本,用于nameNode崩溃时恢复数据
3.定期从nameNode下载EditLog并应用于FsImage。新的FsImage被复制回nameNode,下次启动nameNode时使用它。因此,secondaryNameNode在HDFS中执行常规检查点。因此也被称为CheckpointNode.
SecondaryNamenode通常运行在另一台机器,因为合并操作需要耗费大量的CPU和内存。当Namenode完全崩溃时,会出现数据丢失。 通常做法是拷贝NFS中的备份元数据到Second,将其作为新的主Namenode。
在HA中可以运行一个Hot Standby,作为热备份,在Active Namenode故障之后,替代原有Namenode成为Active Namenode。
secondaryNameNode如何合并FSImage和EditLog
1.secondaryNameNode通过周期性(五分钟),通过getEditLog获取editlog大小,当其达到合并的大小时通过RollEditLog方法进行合并。
2.nameNode停止使用edits文件,并生成一个新的临时的edits.new文件。
3.secondaryNameNode通过nameNode内建的http服务器,以get的方式获取edits与fsimage文件。get方法中携带着fsimage与edits的路径。
4.secondaryNameNode将fsimage载入内存并逐一执行edits中的操作,生成新的fsimage文件。
5.执行结束后,会向nameNode发送http请求,告知nameNode合并结束,nameNode通过http post的方式获取新fsimage文件。
6.nameNode更新fsimage文件中记录检查点执行的时间,并改名为fsimage文件。
7.Edit.new文件更名为edit文件。
注意
:由此可知nameNode与 secondaryNameNode有着相似的内存需求,因为secondaryNameNode也会将fsimage载入内存,因此secondaryNameNode需要运行在一台专门机器上。
在 checkpoint 之前,nameNode故障宕机了,集群不能正常对外提供服务,因为 nameNode 无法查询元数据了,元数据是可以进行恢复的,但是在恢复之前,还不能提供服务。
Block
物理磁盘中有块的概念,磁盘的物理block是磁盘操作最小的单元,读写操作均以block为最小单元,一般为512 Byte。文件系统在物理Block之上抽象了另一层概念,文件系统的block是物理磁盘block的整数倍,都将数据存储为block的集合。因此HDFS将每个文件以block的形式分散存储在Hadoop集群中。在2.x中,每个块的默认大小为128MB(在1.x中为64MB),
block的大小可以根据实际情况进行配置,修改hdfs-site.xml配置文件的dfs.blocksize参数
Block抽象的好处
block的拆分使得单个文件大小可以大于整个磁盘的容量,构成文件的Block可以分布在整个集群, 理论上,单个文件可以占据集群中所有机器的磁盘。
block的抽象也简化了存储系统,对于block,无需关注其权限,所有者等内容(这些内容都在文件级别上进行控制)。
block作为容错和高可用机制中的副本单元,即以block单位进行复制。
为什么要设置设置block的大小为128MB
- 如果块设置过大,
一方面,从磁盘传输数据的时间会明显大于寻址时间,导致程序在处理这块数据时,变得非常慢;
另一方面,mapreduce中的map任务通常一次只处理一个块中的数据,如果块过大运行速度也会很慢。- 如果块设置过小,
一方面存放大量小文件会占用NameNode中大量内存来存储元数据,而NameNode的内存是有限的,不可取;
另一方面文件块过小,寻址时间增大,导致程序一直在找block的开始位置。
因而,块适当设置大一些,减少寻址时间,那么传输一个由多个块组成的文件的时间主要取决于磁盘的传输速率。
文件块越大,寻址时间越短,但磁盘传输时间越长;文件块越小,寻址时间越长,但磁盘传输时间越短。
HDFS中,不需要将文件都以配置的block大小的精确倍数存储(128 MB,256 MB等)。假设有一个514 MB的log文件,如图示。block配置大小为128 MB。将会创建5个block,其中四个block是的128 MB。但是,最后一个块的大小仅为2 MB。
注意
:HDFS的Block块比一般单机文件系统大得多,默认为128M。HDFS的文件被拆分成block-sized的chunk,chunk作为独立单元存储。比block小的文件不会占用整个block,只会占据实际大小。也就是说虽然设置block的大小为128MB,但实际占用空间还是具体存储数据的大小,并不是block的大小
Block Caching
通常情况下,dataNode都是从磁盘上读取block。但是对于经常访问的文件,将其显式得存储在dataNode的内存中显然可以提高效率。这块内存逻辑上就叫做堆外块缓存区(堆外/块/缓存区)。一个block在默认情况下只在一个dataNode上进行缓存,也可以对不同的文件配置不同的缓存节点数。作业调度器会将任务调度到有缓存的节点上,这样就可以极大地提高读取效率。比如在进行join操作时,就可以将较小的表缓存到内存中。
用户或者应用程序可以发送指令给nameNode,配置哪些文件需要缓存,而且还可以配置缓存时间。方法就是在cache pool中添加一条缓存指令(cache directive)。这里提到的cache pool属于管理员组权限区,通过配置它,可以对缓存权限和资源利用情况进行管理。
Replication Management
HDFS提供了一种可靠的方法,将大量数据作为数据块存储在分布式环境中。这些block也被复制以提供容错性。默认的replication factor(备份)是3,这是可配置的。因此,如下图所示,每个block被复制三次并存储在不同的dataNode上(考虑到默认的replication factor)
如果使用默认配置在HDFS中存储128mb的文件,最终将占用384mb(3*128mb)的空间,因为块将被复制三次,将每个副本将存储在不同的dataNode上。
注意
:nameNode定期从dataNode收集block报告以维护复制因子。因此每当block被过度复制或副本数不足时,nameNode会根据需要删除或添加副本。
Rack Awareness(机架感知)
NameNode还确保所有副本不存储在同一个机架或单个机架上。它遵循内置的机架感知算法,以减少延迟并提供容错。考虑到replication为3,机架感知算法表示block的第一个副本将存储在本地机架上,另外两个副本将存储在另外一台机架上和该机架内的另一个dataNode上,如上图。如果有更多的副本,其余的副本将放置在随机dataNode上,如果可能的话,同一机架上保存的副本不超过两个。
这是实际的Hadoop生产集群的样子。在这里有多个机架中包含dataNode的节点:
机架感知的优势
1.提高网络性能:位于不同机架上的节点之间的通信是通过交换机进行的。通常同一机架中的机器之间的网络带宽比位于不同机架中的机器之间的网络带宽要大。因此,机架感知可以减少不同机架之间的写入流量,从而提供更好的写入性能。此外,因为使用多个机架的带宽,将获得更高的读取性能。
2.防止数据丢失:当整个机架因交换机故障或电源故障等,出现了故障,我们也不必担心数据,因为其他的机架还保留着数据的备份;
HDFS Read/ Write Architecture:
现在我们了解一下如何在HDFS上执行数据读/写操作。HDFS遵循
一次写入多次读取
的原则。因此不能编辑已经存储在HDFS中的文件。但是可以通过重新打开文件来追加新数据。
Write
假设一个client 想要写一个名为“example.txt“的文件,文件大小248 MB。
假设block大小配置为128 MB。因此 client 会将”example.txt“分为两个block,一个是128 MB(block a),另一个是120 MB(block b)。
1.首先,client针对两个block向NameNode发出写入请求。
发起写入请求
2.nameNode向client授予写权限,并提供最终将block复制到的dataNodes的ip地址。返回 dataNode地址的列表
3.dataNode的ip地址的选择基于可用性,replication factor(备份)和机架感知随机的基于 基于可用性,机架感知以及备份数随机的
4.假设replication设置为3。因此对于每个block,nameNode都将向客户端提供dataNodes(replication值,即3)的ip地址列表。该列表对于每个block而言都是唯一的。NameNode,返回DataNodes的ip地址列表,并保证每个block的对应ip唯一
5.假设NameNode向客户端提供了以下IP地址列表:
1.对于block a,list a = {DataNode 1的IP,DataNode 4的IP,DataNode 6的IP}
2.对于block b,set b = {DataNode 3的IP,DataNode 7的IP,DataNode 9的IP}
6.每个block 将被复制到三个不同的DataNode中,保证整个集群中保持replication 一致。
7.现在,整个数据复制过程将分三个阶段进行:
1.设置Pipeline
在写入block之前,client确认IP列表中的每个dataNode是否准备好接收数据。在此过程中,client 通过连接该block的列表中的所有dataNode,为每个block创建一个管道(pipeline)。对于 block a NameNode提供的数据节点列表是:
block a list a = {DataNode 1的IP, DataNode 4的IP, DataNode 6的IP}。
因此,对于block a,client将通过以下步骤来创建管道
1.client选择列表中的第一个dataNode(block a 的 dataNode 的ip),即dataNode 1,并将建立TCP/IP连接。
2.client将通知dataNode 1 准备接收该block。并将要需要复制该block另外两个dataNode(4,6)的IP提供给dataNode 1。
3.dataNode 1 将连接到dataNode 4。并通知dataNode 4 准备好接收block,并将dataNode 6 的 ip 提供给dataNode 4。然后dataNode 4 通知dataNode 6 准备好接收block。
4.接下来准备就绪的确认消息,将遵循相反的顺序,即从数据节点6到4,然后到1。
5.最后,dataNode 1 通知client所有的dataNode都准备好了,并在clint 和dataNode 1、4和6之间形成一条管道。
6.至此流水线创建完成,client将开始数据复制或流传输过程。
2.数据流(Data streaming)
创建管道(pipeline)后,client会将数据发送到管道中。HDFS中,数据会根据replication数量进行复制多份。因此block a 将被存储到三个dataNode,默认的replication 为3。接下来client只要将block a 复制到dataNode 1。复制过程由dataNode按顺序完成;
复制期间将执行以下步骤:
1.client写入数据的时候会将数据分解成packets(数据包),并写入数据队列,又dataStreamer消费
2.dataStreamer将packet写入下一个节点,以此类推,直到整个block写完。
3.Pipeline关闭(确认阶段)
一旦block被复制到所有的dataNode中,将进行写入成功的确认,确保client和nameNode成功写入数据。最终client将关闭管道结束TCP会话。
在pipeline之外还存在一个 ack queue队列,用于等待dataNode的确认消息
写入完毕后,等待dataNode的确认消息,只要达到最小副本数的要求,会将成功的信息返回给client
确认消息则按照相反的顺序执行,即从dataNode 6到4,然后到1。最后由dataNode 1将把三个确认(包括自己)消息发送给client。client将通知nameNode数据已成功写入。nameNode更新元数据,client将关闭管道。
同样block b 也将与block a 并行复制到dataNode中,这里需要注意以下事项
:
1.client同时将block a 和block b复制到第一个数据节点。
2.写入时会为每个block将形成一条管道,并且上述所有过程将在这两条管道中并行发生。
3.client将block写入第一个dataNode,然后dataNode将按顺序复制block。
每个block都形成了一个管道,以下是每个block在各自管道中的操作流程:
对于块A:1A-> 2A-> 3A-> 4A
对于块B:1B-> 2B-> 3B-> 4B-> 5B-> 6B
Read
现在我们读取 example.txt文件,那么他的读取流程如下
1.client向nameNode请求文件“ example.txt”的block元数据。
2.nameNode返回存储每个block的dataNode的列表。
3.client将连接到存储block的dataNode。
4.client开始从dataNode并行读取数据(dataNode 1的block a和DataNode 3的block b)就近原则
。
5.client获取带所有的block后,组合所有block形成文件。
HDFS在处理client的读取请求时,会选择最接近client的副本,这会减少了读取耗时与带宽的消耗
在读数据过程中,如果与datanode的通信发生错误,hdfs会试着另外的节点读取数据,并且记住该失败节点, 后续block的读取不会再连接该节点 ,读取一个block之后,会对其进行检验和验证,如果block损坏,尝试从其他节点读取数据,并且将损坏的block汇报给Namenode。
client连接哪个datanode获取数据,是由namenode来指导的,这样可以支持大量并发的客户端请求,namenode尽可能将流量均匀分布到整个集群。
block的位置信息是存储在namenode的内存中,因此相应位置请求非常高效,不会成为瓶颈。
Hadoop -YARN
Hadoop -MapReduce
如有错误欢迎指出