您的位置:首页 > 大数据 > Hadoop

HDFS 总体介绍(一)

2013-06-04 17:00 337 查看
一直以来对hadoop相关系列的学习都是较为零散的,不成体系。没有经过自己总结和沉淀的资料也很难长久的消化和在工作中实际运用。故而也希望通过这样系列的方式对所学习,所了解的资料进行总结。

HDFS(Hadoop Distributed File System)

顾名思义,是hadoop的分布式文件系统。HDFS是hadoop的一个子项目。Hadoop的名字在这里也提一下,是作者小孩很喜欢的一只小象玩具的名字。

HDFS的目标:

1、部署在廉价的PC服务器上。

2、用数据冗余的方式提供高容错性,认为硬件故障是常态。

3、一次写入,多次读取。(简单的数据一致性,所以场景有限)

4、提供高吞吐量,非低延迟。(一般用于离线计算存储)

5、海量数据,超大集群。

架构图



HDFS使用经典的主从结构,由一个NameNode和N个DataNode组成。简单来说,NameNode就是一个维护了什么文件在哪台机器上的元数据集合。而DataNode就是存储实际文件的机器。

从图上可以看出,client要访问文件,会先从NameNode获取到元数据,再访问实际的机器。

而一个NameNode会存在两个问题:

1、为了降低获取元数据的延迟,所有的元数据都常驻内存中,故而有内存限制。

2、单点问题,一旦NameNode挂掉,HDFS就只能人工干预并进行恢复。

这两个问题都可以单独以一个篇幅来讲述,所以在这里仅点到为止。后续的系列中我会单独叙述。

HDFS一般针对大文件,主要由于文件数目越多,NameNode内存越大。这样会大大降低NameNode的工作能力。(针对小文件的优化,在系列中我们会讲到)

DataNode中文件是以block的方式存放的,一个文件可能会被切分成多个block,简单来说一个文件如果是100M,会被切割成一个64M,一个36M的Blocks存储在DataNode中。(每个block默认64M,可配置),一个block中只会有一个文件的内容,当一个文件小于64M的时候,依然独占此block,但是不真正占用磁盘64M。以Block为单位来存放数据的好处是可增加文件读取和写入的并行能力,极大的提高DataNode的磁盘效率,并且对于文件的定位有更好的帮助。

多个block会分布在不同的机器上,并且每个block会有相对应的备份。(默认数目为3)

NameNode得知整体dataNode中的存储情况是通过DataNode定时向NameNode心跳并汇报当前block情况。如果一定的时间内DataNode中没有心跳汇报,NameNode则会认为该DataNode挂掉,进而会进行以下的处理。

1、返回给客户端的机器列表中不再有挂掉的机器。(返回给客户端的机器列表不是namenode主动推送的。是客户端定时从namenode同步一次的。 不过有些版本的hdfs会把这部分信息存储在zookeeper中通知过去。 不过这个成本是有点高的)

2、根据当前集群的情况,将挂掉的机器上的block进行冗余备份,以达到用户配置的冗余数目。(我们说过一份block会有3个备份。 一台机器挂掉了,还有另外两个备份在其他两个机器上。 namenode会判断哪个机器比较合适再放一个备份。 然后把block复制一份过去。 让总体的备份数目达到3)

在这里,笔者也要提出:常见的分布式存储系统,对于性能和容错等问题的优化方式一般是主要有两方面:

1、使用内存(本地内存、分布式内存)。

2、使用数据冗余。

了解整个结构如何协作的最好的方法就是来看如何读、写一个文件,从而能了解到整个流程:

文件写入

流程图:



1、客户端向远程的Namenode发起创建文件请求;

2、Namenode会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会为文件创建一个记录,否则会让客户端抛出异常;

3、当客户端开始写入文件的时候,开发库会将文件切分成多个packets,并在内部以"data queue"的形式管理这些packets,并向Namenode申请新的blocks,获取用来存储replicas的合适的datanodes列表,列表的大小根据在Namenode中对replication的设置而定。

4、开始以pipeline(管道)的形式将packet写入所有的replicas中。开发库把packet以流的方式写入第一个datanode,该datanode把该packet存储之后,再将其传递给在此pipeline中的下一个datanode,直到最后一个datanode,这种写数据的方式呈流水线的形式。

5、最后一个datanode成功存储之后会返回一个ack packet,在pipeline里传递至客户端,在客户端的开发库内部维护着"ack queue",成功收到datanode返回的ack packet后会从"ack queue"移除相应的packet。

6、如果传输过程中,有某个datanode出现了故障,那么当前的pipeline会被关闭,出现故障的datanode会从当前的pipeline中移除,剩余的block会继续剩下的datanode中继续以pipeline的形式传输,同时Namenode会分配一个新的datanode,保持replicas设定的数量。

7、通知NameNode写入成功。NameNode对外提供此文件的访问目录。

文件读取



1、使用HDFS提供的客户端开发库,向远程的Namenode发起RPC请求;

2、Namenode会视情况返回文件的部分或者全部block列表,对于每个block,Namenode都会返回有该block拷贝的datanode地址;

3、客户端开发库会选取离客户端最接近的datanode来读取block;

4、读取完当前block的数据后,关闭与当前的datanode连接,并为读取下一个block寻找最佳的datanode;

5、当读完列表的block后,且文件读取还没有结束,客户端开发库会继续向Namenode获取下一批的block列表。

6、读取完一个block都会进行checksum验证,如果读取datanode时出现错误,客户端会通知Namenode,然后再从下一个拥有该block拷贝的datanode继续读。

本篇文章,我们简单的介绍了HDFS的架构和读写流程,下篇文章,我们会来分析:

HDFS读书笔记-了解NameNode(二)

最后,笔者要说明的是,很多分布式系统的架构、原理、优化方式都是类似的,思考每一个方法的合理性以及适用场景能够帮助我们迅速的了解到其他的分布式系统。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: