HDFS简介

314 阅读28分钟

HDFS(Hadoop Distributed File System )Hadoop分布式文件系统。是根据google发表的论文翻版的。论文为GFS(Google File System)Google 文件系统(中文英文)。

image

image

HDFS + HiveBase 结合,程序先写入HiveBase(支持并发写入),HiveBase再写入HFDFS。

HDFS有很多特点:

① 保存多个副本,且提供容错机制,副本丢失或宕机自动恢复。默认存3份。

② 运行在廉价的机器上。

③ 适合大数据的处理。多大?多小?HDFS默认会将文件分割成block,64M为1个block。然后将block按键值对存储在HDFS上,并将键值对的映射存到内存中。如果小文件太多,那内存的负担会很重。

image

如上图所示,HDFS也是按照Master和Slave的结构。分NameNode、SecondaryNameNode、DataNode这几个角色。

NameNode:是Master节点,是大领导。管理数据块映射;处理客户端的读写请求;配置副本策略;管理HDFS的名称空间;

SecondaryNameNode:是一个小弟,分担大哥namenode的工作量;是NameNode的冷备份;合并fsimage和fsedits然后再发给namenode。

DataNode:Slave节点,奴隶,干活的。负责存储client发来的数据块block;执行数据块的读写操作。

热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作。

冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失。

fsimage:元数据镜像文件(文件系统的目录树。)

edits:元数据的操作日志(针对文件系统做的修改操作记录)

namenode内存中存储的是=fsimage+edits。

SecondaryNameNode负责定时默认1小时,从namenode上,获取fsimage和edits来进行合并,然后再发送给namenode。减少namenode的工作量。


工作原理

写操作:

image

有一个文件FileA,100M大小。Client将FileA写入到HDFS上。

HDFS按默认配置。

HDFS分布在三个机架上Rack1,Rack2,Rack3。

a. Client将FileA按64M分块。分成两块,block1和Block2;

b. Client向nameNode发送写数据请求,如图蓝色虚线①------>。

c. NameNode节点,记录block信息。并返回可用的DataNode,如粉色虚线②--------->。

Block1: host2,host1,host3

Block2: host7,host8,host4

原理:

NameNode具有RackAware机架感知功能,这个可以配置。

若client为DataNode节点,那存储block时,规则为:副本1,同client的节点上;副本2,不同机架节点上;副本3,同第二个副本机架的另一个节点上;其他副本随机挑选。

若client不为DataNode节点,那存储block时,规则为:副本1,随机选择一个节点上;副本2,不同副本1,机架上;副本3,同副本2相同的另一个节点上;其他副本随机挑选。

d. client向DataNode发送block1;发送过程是以流式写入。

流式写入过程,

1>将64M的block1按64k的package划分;

2>然后将第一个package发送给host2;

3>host2接收完后,将第一个package发送给host1,同时client想host2发送第二个package;

4>host1接收完第一个package后,发送给host3,同时接收host2发来的第二个package。

5>以此类推,如图红线实线所示,直到将block1发送完毕。

6>host2,host1,host3向NameNode,host2向Client发送通知,说“消息发送完了”。如图粉红颜色实线所示。

7>client收到host2发来的消息后,向namenode发送消息,说我写完了。这样就真完成了。如图黄色粗实线

8>发送完block1后,再向host7,host8,host4发送block2,如图蓝色实线所示。

9>发送完block2后,host7,host8,host4向NameNode,host7向Client发送通知,如图浅绿色实线所示。

10>client向NameNode发送消息,说我写完了,如图黄色粗实线。。。这样就完毕了。

分析,通过写过程,我们可以了解到:

①写1T文件,我们需要3T的存储,3T的网络流量贷款。

②在执行读或写的过程中,NameNode和DataNode通过HeartBeat进行保存通信,确定DataNode活着。如果发现DataNode死掉了,就将死掉的DataNode上的数据,放到其他节点去。读取时,要读其他节点去。

③挂掉一个节点,没关系,还有其他节点可以备份;甚至,挂掉某一个机架,也没关系;其他机架上,也有备份。

读操作:

image

读操作就简单一些了,如图所示,client要从datanode上,读取FileA。而FileA由block1和block2组成。

那么,读操作流程为:

a. client向namenode发送读请求。

b. namenode查看Metadata信息,返回fileA的block的位置。

block1:host2,host1,host3

block2:host7,host8,host4

c. block的位置是有先后顺序的,先读block1,再读block2。而且block1去host2上读取;然后block2,去host7上读取;

上面例子中,client位于机架外,那么如果client位于机架内某个DataNode上,例如,client是host6。那么读取的时候,遵循的规律是:

优选读取本机架上的数据。

架构设计

概述:HDFS即Hadoop Distributed File System分布式文件系统,它的设计目标是把超大数据集存储到分布在网络中的多台普通商用计算机上,并且能够提供高可靠性和高吞吐量的服务。分布式文件系统要比普通磁盘文件系统复杂,因为它要引入网络编程,分布式文件系统要容忍节点故障也是一个很大的挑战。

设计前提和目标

专为存储超大文件而设计:hdfs应该能够支持GB级别大小的文件;它应该能够提供很大的数据带宽并且能够在集群中拓展到成百上千个节点;它的一个实例应该能够支持千万数量级别的文件。

适用于流式的数据访问:hdfs适用于批处理的情况而不是交互式处理;它的重点是保证高吞吐量而不是低延迟的用户响应

容错性:完善的冗余备份机制

支持简单的一致性模型:HDFS需要支持一次写入多次读取的模型,而且写入过程文件不会经常变化

移动计算优于移动数据:HDFS提供了使应用计算移动到离它最近数据位置的接口

兼容各种硬件和软件平台

不适合的场景

大量小文件:文件的元数据都存储在NameNode内存中,大量小文件会占用大量内存。

低延迟数据访问:hdfs是专门针对高数据吞吐量而设计的

多用户写入,任意修改文件

hdfs架构设计

HDFS主要由3个组件构成,分别是NameNode、SecondaryNameNode和DataNode,HSFS是以master/slave模式运行的,其中NameNode、SecondaryNameNode 运行在master节点,DataNode运行slave节点。

数据块

磁盘数据块是磁盘读写的基本单位,与普通文件系统类似,hdfs也会把文件分块来存储。hdfs默认数据块大小为64MB,磁盘块一般为512B,hdfs块为何如此之大呢?块增大可以减少寻址时间与文件传输时间的比例,若寻址时间为10ms,磁盘传输速率为100MB/s,那么寻址与传输比仅为1%。当然,磁盘块太大也不好,因为一个MapReduce通常以一个块作为输入,块过大会导致整体任务数量过小,降低作业处理速度。

数据块是存储在DataNode中的,为了能够容错数据块是以多个副本的形式分布在集群中的,副本数量默认为3,后面会专门介绍数据块的复制机制。

hdfs按块存储还有如下好处:

文件可以任意大,也不用担心单个结点磁盘容量小于文件的情况

简化了文件子系统的设计,子系统只存储文件块数据,而文件元数据则交由其它系统(NameNode)管理

有利于备份和提高系统可用性,因为可以以块为单位进行备份,hdfs默认备份数量为3。

有利于负载均衡

NameNode

关于NameNode中的元信息

当一个客户端请求一个文件或者存储一个文件时,它需要先知道具体到哪个DataNode上存取,获得这些信息后,客户端再直接和这个DataNode进行交互,而这些信息的维护者就是NameNode。

NameNode管理着文件系统命名空间,它维护这文件系统树及树中的所有文件和目录。NameNode也负责维护所有这些文件或目录的打开、关闭、移动、重命名等操作。对于实际文件数据的保存与操作,都是由DataNode负责。当一个客户端请求数据时,它仅仅是从NameNode中获取文件的元信息,而具体的数据传输不需要经过NameNode,是由客户端直接与相应的DataNode进行交互。

NameNode保存元信息的种类有:

文件名目录名及它们之间的层级关系

文件目录的所有者及其权限

每个文件块的名及文件有哪些块组成

需要注意的是,NameNode元信息并不包含每个块的位置信息,这些信息会在NameNode启动时从各个DataNode获取并保存在内存中,因为这些信息会在系统启动时由数据节点重建。把块位置信息放在内存中,在读取数据时会减少查询时间,增加读取效率。NameNode也会实时通过心跳机制和DataNode进行交互,实时检查文件系统是否运行正常。不过NameNode元信息会保存各个块的名称及文件由哪些块组成。

一般来说,一条元信息记录会占用200byte内存空间。假设块大小为64MB,备份数量是3 ,那么一个1GB大小的文件将占用16*3=48个文件块。如果现在有1000个1MB大小的文件,则会占用1000*3=3000个文件块(多个文件不能放到一个块中)。我们可以发现,如果文件越小,存储同等大小文件所需要的元信息就越多,所以,Hadoop更喜欢大文件。

元信息的持久化

在NameNode中存放元信息的文件是 fsimage。在系统运行期间所有对元信息的操作都保存在内存中并被持久化到另一个文件edits中。并且edits文件和fsimage文件会被SecondaryNameNode周期性的合并(合并过程会在SecondaryNameNode中详细介绍)。

其它问题

运行NameNode会占用大量内存和I/O资源,一般NameNode不会存储用户数据或执行MapReduce任务。

为了简化系统的设计,Hadoop只有一个NameNode,这也就导致了hadoop集群的单点故障问题。因此,对NameNode节点的容错尤其重要,hadoop提供了如下两种机制来解决:

将hadoop元数据写入到本地文件系统的同时再实时同步到一个远程挂载的网络文件系统(NFS)。

运行一个secondary NameNode,它的作用是与NameNode进行交互,定期通过编辑日志文件合并命名空间镜像,当NameNode发生故障时它会通过自己合并的命名空间镜像副本来恢复。需要注意的是secondaryNameNode保存的状态总是滞后于NameNode,所以这种方式难免会导致丢失部分数据(后面会详细介绍)。

DataNode

DataNode是hdfs中的worker节点,它负责存储数据块,也负责为系统客户端提供数据块的读写服务,同时还会根据NameNode的指示来进行创建、删除、和复制等操作。此外,它还会通过心跳定期向NameNode发送所存储文件块列表信息。当对hdfs文件系统进行读写时,NameNode告知客户端每个数据驻留在哪个DataNode,客户端直接与DataNode进行通信,DataNode还会与其它DataNode通信,复制这些块以实现冗余。

NameNode和DataNode架构图

SecondaryNameNode

需要注意,SecondaryNameNode并不是NameNode的备份。我们从前面的介绍已经知道,所有HDFS文件的元信息都保存在NameNode的内存中。在NameNode启动时,它首先会加载fsimage到内存中,在系统运行期间,所有对NameNode的操作也都保存在了内存中,同时为了防止数据丢失,这些操作又会不断被持久化到本地edits文件中。

Edits文件存在的目的是为了提高系统的操作效率,NameNode在更新内存中的元信息之前都会先将操作写入edits文件。在NameNode重启的过程中,edits会和fsimage合并到一起,但是合并的过程会影响到Hadoop重启的速度,SecondaryNameNode就是为了解决这个问题而诞生的。

SecondaryNameNode的角色就是定期的合并edits和fsimage文件,我们来看一下合并的步骤:

合并之前告知NameNode把所有的操作写到新的edites文件并将其命名为edits.new。

SecondaryNameNode从NameNode请求fsimage和edits文件

SecondaryNameNode把fsimage和edits文件合并成新的fsimage文件

NameNode从SecondaryNameNode获取合并好的新的fsimage并将旧的替换掉,并把edits用第一步创建的edits.new文件替换掉

更新fstime文件中的检查点

最后再总结一下整个过程中涉及到NameNode中的相关文件

fsimage :保存的是上个检查点的HDFS的元信息

edits :保存的是从上个检查点开始发生的HDFS元信息状态改变信息

fstime:保存了最后一个检查点的时间戳

数据备份

HDFS通过备份数据块的形式来实现容错,除了文件的最后一个数据块外,其它所有数据块大小都是一样的。数据块的大小和备份因子都是可以配置的。NameNode负责各个数据块的备份,DataNode会通过心跳的方式定期的向NameNode发送自己节点上的Block 报告,这个报告中包含了DataNode节点上的所有数据块的列表。

文件副本的分布位置直接影响着HDFS的可靠性和性能。一个大型的HDFS文件系统一般都是需要跨很多机架的,不同机架之间的数据传输需要经过网关,并且,同一个机架中机器之间的带宽要大于不同机架机器之间的带宽。如果把所有的副本都放在不同的机架中,这样既可以防止机架失败导致数据块不可用,又可以在读数据时利用到多个机架的带宽,并且也可以很容易的实现负载均衡。但是,如果是写数据,各个数据块需要同步到不同的机架,会影响到写数据的效率。

而在Hadoop中,如果副本数量是3的情况下,Hadoop默认是这么存放的,把第一个副本放到机架的一个节点上,另一个副本放到同一个机架的另一个节点上,把最后一个节点放到不同的机架上。这种策略减少了跨机架副本的个数提高了写的性能,也能够允许一个机架失败的情况,算是一个很好的权衡。

关于副本的选择,在读的过程中,HDFS会选择最近的一个副本给请求者。

关于安全模式,当 Hadoop的NameNode节点启动时,会进入安全模式阶段。在此阶段,DataNode会向NameNode上传它们数据块的列表,让 NameNode得到块的位置信息,并对每个文件对应的数据块副本进行统计。当最小副本条件满足时,即一定比例的数据块都达到最小副本数,系统就会退出安全模式,而这需要一定的延迟时间。当最小副本条件未达到要求时,就会对副本数不足的数据块安排DataNode进行复制,直至达到最小副本数。而在安全模式下,系统会处于只读状态,NameNode不会处理任何块的复制和删除命令。

HDFS中的沟通协议

所有的HDFS中的沟通协议都是基于tcp/ip协议,一个客户端通过指定的tcp端口与NameNode机器建立连接,并通过ClientProtocol协议与NameNode交互。而DataNode则通过DataNode Protocol协议与NameNode进行沟通。HDFS的RCP(远程过程调用)对ClientProtocol和DataNode Protocol做了封装。按照HDFS的设计,NameNode不会主动发起任何请求,只会被动接受来自客户端或DataNode的请求。

可靠性保证

可以允许DataNode失败。DataNode会定期(默认3秒)的向NameNode发送心跳,若NameNode在指定时间间隔内没有收到心跳,它就认为此节点已经失败。此时,NameNode把失败节点的数据(从另外的副本节点获取)备份到另外一个健康的节点。这保证了集群始终维持指定的副本数。

可以检测到数据块损坏。在读取数据块时,HDFS会对数据块和保存的校验和文件匹配,如果发现不匹配,NameNode同样会重新备份损坏的数据块。

hdfs文件读写过程剖析

了解客户端与NameNode和DataNode的交互过程十分重要,有助于加深我们对hdfs架构设计的理解。

hdfs文件读取过程

hdfs有一个FileSystem实例,客户端通过调用这个实例的open()方法就可以打开系统中希望读取的文件。hdfs通过rpc调用NameNode获取文件块的位置信息,对于文件的每一个块,NameNode会返回含有该块副本的DataNode的节点地址,另外,客户端还会根据网络拓扑来确定它与每一个DataNode的位置信息,从离它最近的那个DataNode获取数据块的副本,最理想的情况是数据块就存储在客户端所在的节点上。

hdfs会返回一个FSDataInputStream对象,FSDataInputStream类转而封装成DFSDataInputStream对象,这个对象管理着与DataNode和NameNode的I/O,具体过程是:

1. 客户端发起读请求

2. 客户端与NameNode得到文件的块及位置信息列表

3. 客户端直接和DataNode交互读取数据

4. 读取完成关闭连接

1

2

3

4

当FSDataInputStream与DataNode通信时遇到错误,它会选取另一个较近的DataNode,并为出故障的DataNode做标记以免重复向其读取数据。FSDataInputStream还会对读取的数据块进行校验和确认,发现块损坏时也会重新读取并通知NameNode。

这样设计的巧妙之处:

让客户端直接联系DataNode检索数据,可以使hdfs扩展到大量的并发客户端,因为数据流就是分散在集群的每个节点上的,在运行MapReduce任务时,每个客户端就是一个DataNode节点。

NameNode仅需相应块的位置信息请求(位置信息在内存中,速度极快),否则随着客户端的增加,NameNode会很快成为瓶颈。

关于hadoop与网络拓扑

在海量数据处理过程中,主要限制因素是节点之间的带宽。衡量两个节点之间的带宽往往很难实现,在这里hadoop采取了一个简单的方法,它把网络拓扑看成是一棵树,连个节点的距离=它们到最近共同祖先距离的总和,而树的层次可以这么划分:

同一节点中的进程

同一机架上的不同节点

同一数据中心不同机架

不同数据中心的节点

若数据中心d1中一个机架r1中一个节点n1表示为d1/r1/n1,则:

distance(d1/r1/n1,d1/r1/n1)=0;

distance(d1/r1/n1,d1/r1/n2)=2;

distance(d1/r1/n1,d1/r2/n3)=4;

distance(d1/r1/n1,d2/r3/n4)=6;

1

2

3

4

hdfs文件写入过程

hdfs有一个DistributedFileSystem实例,客户端通过调用这个实例的create()方法就可以创建文件。DistributedFileSystem会发送给NameNode一个RPC调用,在文件系统的命名空间创建一个新文件,在创建文件前NameNode会做一些检查,如文件是否存在,客户端是否有创建权限等,若检查通过,NameNode会为创建文件写一条记录到本地磁盘的EditLog,若不通过会向客户端抛出IOException。创建成功之后DistributedFileSystem会返回一个FSDataOutputStream对象,客户端由此开始写入数据。

同读文件过程一样,FSDataOutputStream类转而封装成DFSDataOutputStream对象,这个对象管理着与DataNode和NameNode的I/O,具体过程是:

1. 客户端在向NameNode请求之前先写入文件数据到本地文件系统的一个临时文件

2. 待临时文件达到块大小时开始向NameNode请求DataNode信息

3. NameNode在文件系统中创建文件并返回给客户端一个数据块及其对应DataNode的地址列表(列表中包含副本存放的地址)

4. 客户端通过上一步得到的信息把创建临时文件块flush到列表中的第一个DataNode

5. 当文件关闭,NameNode会提交这次文件创建,此时,文件在文件系统中可见

1

2

3

4

5

上面第四步描述的flush过程实际处理过程比较负杂,现在单独描述一下:

1. 首先,第一个DataNode是以数据包(数据包一般4KB)的形式从客户端接收数据的,DataNode在把数据包写入到本地磁盘的同时会向第二个DataNode(作为副本节点)传送数据。

2. 在第二个DataNode把接收到的数据包写入本地磁盘时会向第三个DataNode发送数据包

3. 第三个DataNode开始向本地磁盘写入数据包。此时,数据包以流水线的形式被写入和备份到所有DataNode节点

4. 传送管道中的每个DataNode节点在收到数据后都会向前面那个DataNode发送一个ACK,最终,第一个DataNode会向客户端发回一个ACK

5. 当客户端收到数据块的确认之后,数据块被认为已经持久化到所有节点。然后,客户端会向NameNode发送一个确认

6. 如果管道中的任何一个DataNode失败,管道会被关闭。数据将会继续写到剩余的DataNode中。同时NameNode会被告知待备份状态,NameNode会继续备份数据到新的可用的节点

7. 数据块都会通过计算校验和来检测数据的完整性,校验和以隐藏文件的形式被单独存放在hdfs中,供读取时进行完整性校验

1

2

3

4

5

6

7

hdfs文件删除过程

hdfs文件删除过程一般需要如下几步:

1. 一开始删除文件,NameNode只是重命名被删除的文件到/trash目录,因为重命名操作只是元信息的变动,所以整个过程非常快。在/trash中文件会被保留一定间隔的时间(可配置,默认是6小时),在这期间,文件可以很容易的恢复,恢复只需要将文件从/trash移出即可。

2. 当指定的时间到达,NameNode将会把文件从命名空间中删除

3. 标记删除的文件块释放空间,HDFS文件系统显示空间增加

整合版本

HDFS****运行原理

HDFS****简介

HDFS(Hadoop Distributed File System )Hadoop分布式文件系统。是根据google发表的论文翻版的。论文为GFS(Google File System)Google 文件系统(中文英文)。

HDFS有很多特点:

  1. 保存多个副本,且提供容错机制,副本丢失或宕机自动恢复。默认存3份。为防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其他某几个主机上。

  2. 运行在廉价的机器上。

  3. 适合大数据的处理。HDFS会将一个完整的大文件平均分块存储到不同计算机上,默认会将文件分割成block,64M为1个block。然后将block按键值对存储在HDFS上,并将键值对的映射存到内存中。如果小文件太多,那内存的负担会很重。

  4. 流式数据访问,一次写入多次读写,和传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化只能在文件末尾添加

HDFS****架构原理

HDFS 架构原理HDFS采用Master/Slave架构。

  1. 一个HDFS集群包含一个单独的NameNode和多个DataNode。

  2. NameNode作为Master服务,它负责管理文件系统的命名空间和客户端对文件的访问。NameNode会保存文件系统的具体信息,包括文件信息、文件被分割成具体block块的信息、以及每一个block块归属的DataNode的信息。对于整个集群来说,HDFS通过NameNode对用户提供了一个单一的命名空间。

  3. DataNode作为Slave服务,在集群中可以存在多个。通常每一个DataNode都对应于一个物理节点。DataNode负责管理节点上它们拥有的存储,它将存储划分为多个block块,管理block块信息,同时周期性的将其所有的block块信息发送给NameNode。

下图为HDFS系统架构图,主要有三个角色,Client、NameNode、DataNode。

image

image.png

HDFS的一些关键元素

  • Block:将文件分块,通常为64M。

  • NameNode:是Master节点,是大领导。管理数据块映射;处理客户端的读写请求;配置副本策略;管理HDFS的名称空间。保存整个文件系统的目录信息、文件信息及分块信息,由唯一一台主机专门保存。

  • SecondaryNameNode:是一个小弟,分担大哥NameNode的工作量;是NameNode的冷备份;合并fsimage和fsedits然后再发给NameNode。(热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作。冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失。)

  • DataNode:是Slave节点,奴隶,干活的。负责存储Client发来的数据块block;执行数据块的读写操作。

  • fsimage:元数据镜像文件(文件系统的目录树)

  • edits:元数据的操作日志(针对文件系统做的修改操作记录)

HDFS设计重点

  1. HDFS 数据备份HDFS被设计成一个可以在大集群中、跨机器、可靠的存储海量数据的框架。它将所有文件存储成block块组成的序列,除了最后一个block块,所有的block块大小都是一样的。

  2. HDFS中的文件默认规则是write one(一次写、多次读)的,并且严格要求在任何时候只有一个writer。

  3. NameNode全权管理数据块的复制,它周期性地从集群中的每个DataNode接受心跳信号和块状态报告(BlockReport)。接收到心跳信号以为该DataNode工作正常,块状态报告包含了一个该DataNode上所有数据块的列表。

  4. NameNode内存中存储的是=fsimage+edits。SecondaryNameNode负责定时(默认1小时)从NameNode上,获取fsimage和edits来进行合并,然后再发送给NameNode。减少NameNode的工作量。

image

image.png

文件写入

Client向NameNode发起文件写入的请求。

  1. NameNode根据文件大小和文件块配置情况,返回给Client它所管理部分DataNode的信息。

  2. Client将文件划分为多个block块,并根据DataNode的地址信息,按顺序写入到每一个DataNode块中。

以下过程完全参考自(【Hadoop】HDFS的运行原理

image

image.png

例如:有一个文件FileA,100M大小。Client将FileA写入到HDFS上。

  1. HDFS按默认配置。

  2. HDFS分布在三个机架上Rack1,Rack2,Rack3。

文件写入过程如下:

  1. Client将FileA按64M分块。分成两块,block1和Block2;

  2. Client向NameNode发送写数据请求,如图蓝色虚线①------>。

  3. NameNode节点,记录block信息。并返回可用的DataNode,如粉色虚线②--------->。

    1. Block1: host2,host1,host3

    2. Block2: host7,host8,host4

    3. 原理:

      1. NameNode具有RackAware机架感知功能,这个可以配置。

      2. 若Client为DataNode节点,那存储block时,规则为:副本1,同Client的节点上;副本2,不同机架节点上;副本3,同第二个副本机架的另一个节点上;其他副本随机挑选。

      3. 若Client不为DataNode节点,那存储block时,规则为:副本1,随机选择一个节点上;副本2,不同副本1,机架上;副本3,同副本2相同的另一个节点上;其他副本随机挑选。

  4. Client向DataNode发送block1;发送过程是以流式写入。流式写入过程如下:

    1. 将64M的block1按64k的package划分;

    2. 然后将第一个package发送给host2;

    3. host2接收完后,将第一个package发送给host1,同时Client想host2发送第二个package;

    4. host1接收完第一个package后,发送给host3,同时接收host2发来的第二个package。

    5. 以此类推,如图红线实线所示,直到将block1发送完毕。

    6. host2,host1,host3向NameNode,host2向Client发送通知,说“消息发送完了”。如图粉红颜色实线所示。

    7. Client收到host2发来的消息后,向NameNode发送消息,说我写完了。这样就真完成了。如图黄色粗实线

    8. 发送完block1后,再向host7、host8、host4发送block2,如图蓝色实线所示。

    9. 发送完block2后,host7、host8、host4向NameNode,host7向Client发送通知,如图浅绿色实线所示。

    10. Client向NameNode发送消息,说我写完了,如图黄色粗实线。。。这样就完毕了。

  5. 分析:通过写过程,我们可以了解到

    1. 写1T文件,我们需要3T的存储,3T的网络流量贷款。

    2. 在执行读或写的过程中,NameNode和DataNode通过HeartBeat进行保存通信,确定DataNode活着。如果发现DataNode死掉了,就将死掉的DataNode上的数据,放到其他节点去。读取时,要读其他节点去。

    3. 挂掉一个节点,没关系,还有其他节点可以备份;甚至,挂掉某一个机架,也没关系;其他机架上,也有备份。

文件读取

当文件读取:

  1. Client向NameNode发起文件读取的请求。

  2. NameNode返回文件存储的block块信息、及其block块所在DataNode的信息。

  3. Client读取文件信息。

image

image.png

如图所示,Client要从DataNode上,读取FileA。而FileA由block1和block2组成。读操作流程如下:

  1. Client向NameNode发送读请求。

  2. NameNode查看Metadata信息,返回FileA的block的位置。

    1. block1:host2,host1,host3

    2. block2:host7,host8,host4

  3. block的位置是有先后顺序的,先读block1,再读block2。而且block1去host2上读取;然后block2,去host7上读取。

上面例子中,Client位于机架外,那么如果Client位于机架内某个DataNode上,例如,Client是host6。那么读取的时候,遵循的规律是:优选读取本机架上的数据。

问题:如果读取block是按照先后顺序读,是否意味着在不同副本之间的读取是不平均的,没有考虑通过负载策略来提高读效率吗?

备份数据的存放

备份数据的存放是HDFS可靠性和性能的关键。HDFS采用一种称为rack-aware的策略来决定备份数据的存放。

通过一个称为Rack Awareness的过程,NameNode决定每个DataNode所属rack id。

缺省情况下,一个block块会有三个备份:

  1. 一个在NameNode指定的DataNode上

  2. 一个在指定DataNode非同一rack的DataNode上

  3. 一个在指定DataNode同一rack的DataNode上。

这种策略综合考虑了同一rack失效、以及不同rack之间数据复制性能问题。

副本的选择:为了降低整体的带宽消耗和读取延时,HDFS会尽量读取最近的副本。如果在同一个rack上有一个副本,那么就读该副本。如果一个HDFS集群跨越多个数据中心,那么将首先尝试读本地数据中心的副本。