2、HDFS:Hadoop Distributed File System

2.1、HDFS存储架构剖析

2.1.1、Namenode

  • Namenode 是一个中心服务器,单一节点(简化系统的设计和实现),负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。
  • 文件操作,NameNode 负责文件元数据的操作DataNode负责处理文件内容的读写请求,跟文件内容相关的数据流不经过NameNode,只会询问它跟那个DataNode联系,否则NameNode会成为系统的瓶颈。
  •  副本存放在哪些DataNode上由 NameNode来控制,根据全局情况做出块放置决定,读取文件时NameNode尽量让用户先读取最近的副本,降低带块消耗和读取时延
  •  Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。

心跳机制:datanode每隔3秒向namenode发送心跳信息

2.1.2、DataNode

  • 一个数据块在DataNode以文件存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和以及时间戳。
  • DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。
  • 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode 的心跳,则认为该节点不可用。
  • 集群运行中可以安全加入和退出一些机器。
  • 专门用来储存文件,文件被分为多个block块储存在datanode节点上,为了保护数据的安全,默认会有三个副本数,会随机的分配在不同datanode上(就近原则)。

2.1.3、文件

  • 文件切分成块(默认大小128M),以块为单位,每个块有多个副本存储在不同的机器上,副本数可在文件生成时指定(默认3)。
  • NameNode是主节点,存储文件的元数据如文件名,文件目录结构,文件属性(生成时间,副本数,文件权限),以及每个文件的块列表以及块所在的DataNode等等。
  • DataNode 在本地文件系统存储文件块数据,以及块数据的校验和。
  • 可以创建、删除、移动或重命名文件,当文件创建、写入和关闭之后不能修改文件内容。

2.1.4、数据损坏处理

  • DataNode读取block的时候,它会计算checksum。
  • 如果计算后的checksum,与block创建时值不一样,说明该block已经损坏。
  • Client读取其它DataNode上的block。
  • NameNode标记该块已经损坏,然后复制block达到预期设置的文件备份数。
  • DataNode 在其文件创建后三周验证其checksum。

2.2、Namenode启动流程

  

  注:NameNode数据存放在两个地方,一个是内存,一个是本地磁盘。在磁盘中的存储分为fsimage(镜像文件)、edits(编辑日志文件)。

2.2.1、Namenode启动过程

1)第一次启动hdfs,我们需要格式化hdfs文件系统。

hdfs bin/hdfs namenode -format

格式化hdfs的后我们会生成fsimage镜像文件,存储文件系统的元数据。 

2)格式化hdfs后,启动NameNode。首先将fsimage(镜像)载入内存,并执行(replay)编辑日志editlog的的各项操作;获取文件的元数据如文件名,文件目录结构,文件属性(生成时间、副本数、文件权限)以及每个文件的块列表和块的位置。 

3)一旦在内存中建立文件系统元数据映射,则创建一个新的fsimage文件(这个过程不需SecondaryNameNode)和一个空的editlog;

4)启动DataNode,启动DataNode首先会向NameNode去注册,然后会向NameNode发送一些块的报告。NameNode为了核对dataNode上的块(数据)是否有缺失情况。(在安全模式下)

5)此刻namenode运行在安全模式。即NameNode的文件系统对于客服端来说是只读的。(显示目录,显示文件内容等。写、删除、重命名都会失败);

6)当用户用文件系统对文件进行创建、上传、读取、删除等操作的时候,NameNode会将这些操作写入编辑日志文件edits中。由此看出edits这个文件存放的是文件系统中元数据的变化信息。

7)第二次启动hdfs,启动NameNode ,nameNode首先读取镜像文件fsimage和编辑日志文件edits,这时候,nameNode 拥有完整的元数据,加载到内存,然后创建一个新的fsimage文件,并创建一个新的edits文件。然后接着走第一次启动的4.5.6步骤。

2.2.2、元数据合并流程

NameNode的元数据信息先往edits文件中写,当edits文件达到一定的阈值(3600秒或大小到64M)的时候,会开启合并的流程。

1)当开始合并的时候,SecondaryNameNode会把edits和fsimage拷贝到所在服务器所在内存中,合并生成名为fsimage.ckpt的文件。

2)将fsimage.ckpt文件拷贝到NameNode上,删除原有的fsimage,并将fsimage.ckpt重命名为fsimage。

3)当SecondaryNameNode将edits和fsimage拷贝走之后,NameNode会立刻生成一个edits.new文件,用于记录新来的元数据,当合并完成之后,原有的edits文件才会被删除,并将edits.new文件重命名为edits文件,开启下一轮流程。

配置合并的阈值

<property>

    <name>dfs.namenode.checkpoint.period</name>

    <value>3600</value>

</property>

<property>

    <name>fs.checkpoint.size</name>

    <value>67108864</value>

</property>

2.2.3、安全模式:safemode

Namenode的一种状态,启动时会自动进入安全模式,在安全模式,文件系统不允许有任何修改,“只读不写”。目的,是在系统启动时检查各个DataNode上数据的有效性。

1)Namenode启动会自动进入安全模式。

2)手动进入安全模式。

bin/hdfs dfsadmin -safemode enter 进入安全模式

bin/hdfs dfsadmin -safemode leave 离开安全模式

3)阀值=0.999

datanode会周期性的报告block信息。

Namenode会计算block的损坏率,

当阀值<0.999f时系统会进入安全模式,HDFS只读不写。

配置安全模式临界值,默认

<property>

    <name>dfs.namenode.safemode.threshold-pct</name>

    <value>0.999f</value>

</property>

2.3、HDFS的特点

2.3.1、HDFS的优点

1)处理超大文件:这里的超大文件通常是指百MB、数百TB大小的文件。目前在实际应用中,HDFS已经能用来存储管理PB级的数据了。

2)流式的访问数据:HDFS的设计建立在更多地响应"一次写入、多次读取"任务的基础上。这意味着一个数据集一旦由数据源生成,就会被复制分发到不同的存储节点中,然后响应各种各样的数据分析任务请求。在多数情况下,分析任务都会涉及数据集中的大部分数据,也就是说,对HDFS来说,请求读取整个数据集要比读取一条记录更加高效。

3)运行于廉价的商用机器集群上:Hadoop设计对硬件需求比较低,只须运行在低廉的商用硬件集群上,而无需昂贵的高可用性机器上。廉价的商用机也就意味着大型集群中出现节点故障情况的概率非常高。这就要求设计HDFS时要充分考虑数据的可靠性,安全性及高可用性。

2.3.2、HDFS的缺点

1)不适合低延迟数据访问:如果要处理一些用户要求时间比较短的低延迟应用请求,则HDFS不适合。HDFS是为了处理大型数据集分析任务的,主要是为达到高的数据吞吐量而设计的,这就可能要求以高延迟作为代价。

2)无法高效存储大量小文件:因为Namenode把文件系统的元数据放置在内存中,所以文件系统所能容纳的文件数目是由Namenode的内存大小来决定。一般来说,每一个文件、文件夹和Block需要占据150字节左右的空间,所以,如果你有100万个文件,每一个占据一个Block,你就至少需要300MB内存。当前来说,数百万的文件还是可行的,当扩展到数十亿时,对于当前的硬件水平来说就没法实现了。还有一个问题就是,因为Map task的数量是由splits来决定的,所以用MR处理大量的小文件时,就会产生过多的Maptask,线程管理开销将会增加作业时间。举个例子,处理10000M的文件,若每个split为1M,那就会有10000个Maptasks,会有很大的线程开销;若每个split为100M,则只有100个Maptasks,每个Maptask将会有更多的事情做,而线程的管理开销也将减小很多。

3)不支持多用户写入及任意修改文件:HDFS的一个文件中只有一个写入者,而且写操作只能在文件末尾完成,即只能执行追加操作。目前HDFS还不支持多个用户对同一文件的写操作,以及在文件任意位置进行修改。

2.4、HDFS文件读写流程(hadoop 2.0x中一个block为128M)

2.4.1、HDFS文件写流程

 

有一个文件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上的数据,放到其他节点去。读取时,

要读其他节点去。

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

 

 2.4.2、HDFS文件读流程

 

如图所示,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。那么读取的时候,遵循的规律是:

优选读取本机架上的数据

 

 

2.5、HDFS数据安全性如何保证

1) 存储在HDFS系统上的文件,会分割成128M大小的block存储在不同的节点上,block的副本数默认3份,也可配置成更多份;

2) 第一个副本一般放置在与client(客户端)所在的同一节点上(若客户端无datanode,则随机放),第二个副本放置到与第一个副本同一机架的不同节点,第三个副本放到不同机架的datanode节点,当取用时遵循就近原则;

3) datanode已block为单位,每3s报告心跳状态,若10min内不报告心跳状态则namenode认为block已死掉,namonode会把其上面的数据备份到其他一个datanode节点上,保证数据的副本数量;

4) datanode会默认每小时把自己节点上的所有块状态信息报告给namenode

5) 采用safemode模式:datanode会周期性的报告block信息。Namenode会计算block的损坏率,当阀值<0.999f时系统会进入安全模式,HDFS只读不写。 HDFS元数据采用secondaryname备份或者HA备份。