一、HDFS的读写流程

hadoop备份策略 hdfs 备份_hadoop备份策略

图1-1 HDFS Client数据获取流程

HDFS读写流程涉及到三种角色,分别是HDFS Client,NameNode和DataNode。HDFS Cilent为应用程序提供了访问HDFS集群的接口。NameNode的内存中保存着整个分布式文件系统的目录树和元数据,元数据包含了文件与块(Block,默认64MB,可配置)的对应关系,块与DataNode的对应关系。DataNode保存了实际的Block数据。三者之间通过TCP/IP协议进行交互。具体的流程如下:

1. HDFS Client通过配置文件获取NameNode的IP地址和端口(HDFS配置文件后续会详细讲解);

2. HDFS Client通过网络连接NameNode,并发送数据访问请求(请求中包含文件路径和文件名);

3. NameNode接收到请求以后,查找内存中的目录树找到对应的文件,查看该文件对应的分块,以及每个分块对应的位置(DataNode的机器名,并将Block id和DataNode List 返回给HDFS Client;

4. HDFS Client获取Block及其对应的DataNode以后,连接DataNode并发送数据访问请求,请求中包含了Block id;

5. DataNode接收到来自HDFS Client的请求后,根据Block id 在本地磁盘中读取实际的数据,并返回给HDFS Client。

注意,如果一个文件对应多个不同的Block,HDFS Client会针对每个不同的Block发起一次请求。

hadoop备份策略 hdfs 备份_数据_02

图1-2HDFS Client的详细数据获取流程

图1-2 描述详细的数据获取流程,与本地文件系统相比,HDFS Client也存在常见的文件操作如打开文件(open),读取数据(read)和关闭文件(close)。与本地文件系统不同的是HDFS Client通过网络方式来完成以上这些操作。HDFS Client运行在java 虚拟机中,借助Distributed FileSystem与NameNode交互,借助FSDataInputStream与DataNode进行交互。如果要访问的文件对应两个Block,那就按顺序分别获取两个Block对应的数据(如图中的步骤4和5)。

hadoop备份策略 hdfs 备份_数据_03

图1-3HDFS Client 数据写入示意图

HDFS Client在往HDFS写入数据时的过程如下:

1. 通过对象Distributed FileSystem向NameNode发送创建文件的请求,

2. NameNode在目录树中增加文件名,产生Block id,选择三个DataNode(默认情况下,有两个DataNode在同一个机柜中,其中第一个DataNode为该Block的主存储节点);

3. NameNode返回Blcok id和DataNode的地址信息;

4. HDFS Client获取DataNode地址以后,连接该Block的主存储节点,并将Block id与实际数据提交到主存储节点;

5. 主存储节点接收到数据以后,一方面将数据放置到本地磁盘,一方面将数据传输到下一个DataNode,三个DataNode形成了一个pipeline;

6. 最后一个DataNode保存好数据以后,向前一个DataNode发送确认信息。

二、 HDFS的高可靠性设计

高可靠性涉及DataNode的可靠性和NameNode的可靠性。

hadoop备份策略 hdfs 备份_目录树_04

图1-4数据的备份示意图

如图1-4所示,bi代表了Block的id,集群中每个Block 都备份了3个,分布在集群中三个不同的DataNode上。当某个节点失效时,会停止向NameNode发送心跳。一段时间后,NameNode发现该DataNode失去联系,查找BlockMap(保存了Block id和DataNode的映射关系)受到影响的所有Block id。这些Block id有个共同点,备份数已经由三下降到二,NameNode会为受影响的Block 再增加一个备份数据。假设图1-4中的第一个DataNode(DN1)宕机导致b1的被分数下降,NameNode会通知DN3将数据b1复制一份到DN2,这样b1的备份数又回到了3。

   在讨论了DataNode的高可靠性以后,我们接下来讨论NameNode(NN)的高可靠性。

hadoop备份策略 hdfs 备份_目录树_05

图1-5 内存目录树与镜像文件

hadoop备份策略 hdfs 备份_hadoop备份策略_06

图1-6镜像文件的合并

  HDFS在工作状态下,整个文件系统的目录树和元数据都保存在NameNode(NN)的内存中。考虑一种情况,如果集群断电,NN内存中的数据就会丢失且不可恢复,整个集群无法正常工作。

  因此,HDFS针对NN的设计考虑了到了高可靠性。与内存目录树对应的是保存在NN本地磁盘中的镜像文件fsimage(如图1-5所示)。如何将目录树转化成顺序的文件形式可以参考数据结构中的线索化二叉树,确保目录树中每个节点有唯一的访问顺序即可。

 在使用HDFS的过程中,目录树会经常被修改(如新建文件和文件夹,数据删除,数据拷贝、文件重命名等操作)。如果时刻保持fsimage与内存目录树的一致,将会导致频繁的IO操作,严重降低HDFS的使用。因此,HDFS引入editlog,在一段时间内对目录树的操作,同时也以日志方式保存在editlog中,Editlog与fsimage定期进行合并,这样保持fsimage与内存目录树的一致。同学们也可以思考一下整个时间设置在什么范围比较合适?是不是时间越长越好?(若时间很长,editlog很大,断电以后重启时,fsimage和edit的合并会花费很长的时间,导致集群启动非常慢)。图1-5和图1-6详细的描述了这个过程。

hadoop备份策略 hdfs 备份_HDFS_07

图1-7NameNode与SecondNameNode的交互

HDFS引入的SNN,考虑了两个方面的情况:一,NN上只需负责处理对目录树的访问请求,至于fsimage和editlog的合并交给SNN执行;二,NN磁盘损坏时,SNN可以快速替代NN。SNN与NN的具体交互流程如下:

1. SNN会定期和NN通信,请求其停止使用EditLog文件,暂时将新的写操作写到一个新的文件edit.new上来,这个操作是瞬间完成,上层写日志的函数完全感觉不到差别;

2. SNN通过HTTP GET方式从NN上获取到FsImage和EditLog文件,并下载到本地的相应目录下;

3. SNN将下载下来的FsImage载入到内存,然后一条一条地执行EditLog文件中的各项更新操作,使得内存中的FsImage保持最新;这个过程就是EditLog和FsImage文件合并;

4. SNN执行完(3)操作之后,会通过post方式将新的FsImage文件发送到NN节点上;

5. NN将从SNN接收到的新的FsImage替换旧的FsImage文件,同时将edit.new替换EditLog文件,通过这个过程EditLog就变小了。

三、思考题

3.1 DataNode之间的数据传输方式

   假设数据块大小64MB,考虑以下两种数据传输方式:

    a. 同步阻塞式传输,主DataNode完整接收到HDFS Client传输的64MB  数据以后,再将数据传给后继DataNode;

     b. 异步非阻塞式传输,主DataNode接收一小块数据packet(例如1MB),将这一小块数据发送给下一个DataNode,同时开始接收下一小块数据;

3.2 数据备份个数对性能的影响

    假设以第二种方式传输数据,数据备份数为2、3或4对程序性能的影响有多大?