一、HDFS相关概念简介
关于HDFS百度百科介绍如下:

HDFS相关概念及体系简介
-
HDFS:Hadoop Distributed File System,使用JAVA语言实现的分布式、可横向扩展的文件系统
-
它包含一个名称节点NameNode和多个数据节点DataNode,属于主/从(Master/Slave)关系结构模型
-
名称节点,负责管理文件系统命名空间及客户端对文件的访问,它是一个中心服务器
-
数据节点,一般来说是一个节点运行一个数据节点进程,每个数据节点上的数据实际上保存在本地的Linux文件系统中,负责处理文件系统客户端读/写请求,或删除、创建和复制数据块等操作
HDFS的设计理念
设计的目标:大数据量存储、低成本及高容错率、数据一致性、顺序访问数据
-
大数据量存储
存储总量可以达到PB/EB级别,普通单个文件一般在几百MB
-
低成本及高容错率
本身Hadoop运行不需要在昂贵的设备上,这就意味着对于集群来说,节点发生一故障的可能性更高,从而在设计上HDFS就考虑到了这种高容错的机制,保障在遇到故障时客户可以无明显感知
-
数据一致性
-
顺序访问数居
HDFS更适合于处理批量数据,而不适合随机定位访问
HDFS的优缺点
-
优点
高容错性,多个副本的存在保证了这种容错性
适合批处理
适合大数据处理(数据规模上可以达到GB、TB甚至是PB级别数据;文件规模上可以处理百万规模以上的文件数量;节点规模上可以处理10K节点的规模)
对于设备没有特别的要求
-
缺点
不适合低延迟时数据访问(如:毫秒级来存储数据做不到)
不适合于小文件的存取,它会占用NameNode大量的内存来存储文件、目录和块信息;小文件存储的寻道时间会超过读取时间
并发写入,文件随机修改,一个文件只能有一个写入者,仅支持append(日志),不允许修改文件
HDFS的执行原理简介
客户端有文件读写请求--->NameNode(名称节点,管理节点)接收到读写服务请求--->根据Metadata元数据(包含元数据的镜像fsimage、操作日志edits信息)等信息--->与DataNode进行通信,进行资源的协调--->Secondary NameNode进行edits和fsimage的合并,同时DataNode之间进行数据复制。
如果要进行大文件存储其操作的方式如下:
对文件进行按块切割,分别把它们放在不同的节点,每个文件都会有3个副本备份,并且同时会有一个记录文件块存放情况的元数据文件以备查询。
二、HDFS核心概念介绍
通过上面对HDFS的概念简介我们对HDFS有了一个宏观上的简单了解,下面则介绍一下HDFS中的核心概念以便于未来对于HDFS原理的深入理解
-
block数据块
block块,它概念类似于磁盘中的数据块大小,是磁盘上的早小读写单位,在HDFS中也有块的概念。HDFS 1.x中默认的数据块大小是64MB;HDFS 2.x中默认的块大小是128MB。
注意:这里的块的大小与磁盘不同的是当一个文件大小小于数据块的默认大小时并不会占满整个块的空间(如,只有一个10MB的文件存储在一个128MB的块中时,文件只会占用10MB的磁盘空间),但是磁盘的上的文件系统则是不够最小块大小时也会占一个块空间的大小。
-
NameNode
它是HDFS集群中的管理节点。一个集群中通常只有一台活动的NameNode它存放了HDFS的元数据具一个集群只有一份元数据存在
NameNode中保存的Metadata信息包括文件ownership、permissions、文件有哪些block、block存放在哪些DataNode等
-
DataNode
DataNode为数据节点,它其中的文件的存储方式是按大小分成若干个block,存储到不同的节点上,block大小和副本数通过客户端上传文件时设置,文件上传成功后,副本数可以改变,但是块的大小是不可以变更的。默认情况下每个block都有3个副本
-
SecondaryNameNode
它有简称为SNN,主要的工作是帮NameNode合并 edits,减少NameNode启动时间,SNN执行合并的时机有如下两个:
配置文件中设置的时间间隔fs.check-point.period,默认为3600秒(默认配置是一个小时合并一次)
配置 文件中设置edits log大小fs.check-point.size,规定edits文件的最大值默认为64MB
-
元数据
元数据保存在NameNode的内存当中,这样可以加速查询,它就要包含fsimage和edits
fsimage:元数据镜像文件(保存文件系统的目录树)
edits:元数据操作日志(针对元数据的修改操作)
三、HDFS读取文件的流程
对于存储在HDFS上的文件客户端读取的流程如下:
-
客户端调用FileSystem对象的open()方法打开要读取的文件。这个对象是DistrbutedFileSystem的一个实例
-
DistrbutedFileSystem通过使用远程过程调用(RPC)来调用NameNode,确定文件起始块位置
-
对于每个block,NameNode返回到存有这个块副本的DataNode地址。同时,这些DataNode根据它们与客户端的距离来排序,DistrbutedFileSystem类返回一个FSDataInputStream对象给客户端并读取数据,FSDataInputStream转而封装DFSInputStream对象,这个对象管理着DataNode和NameNode的I/O。客户端对输入流调用read()方法
-
存储文件起始几个块的DataNode地址的DFSInputStream,接下来会连接距离最近的文件中第一个块所在DataNode。通过对数据反复调用read()方法,实现把数据从DataNode传输到客户端
-
当临近块的未端时,DFSInputStream会关闭与这个DataNode的连接,然后去寻找下一个最佳的DataNode
-
客户端从流中读取数据时,块是按打开的DFSInputStream与DataNode新建连接的顺序进行读取的,也可以根据需要询问NameNode从而检索下一批数据块的DataNode的位置,一旦客户端完成读取就对FSDataInputStream调用close()方法
四、HDFS写文件流程
对于存储在HDFS上的文件也可以写入内容,客户端发送写文件的流程如下:
-
客户端调用DistributedFileSystem对象create()方法新建文件
-
DistributedFileSystem对NameNode创建一个RPC调用,在文件命名这间中创建一个新文件,这个时候文件中没有相应的数据块
-
NameNode检查来确定空上文件不存在而且客户端有新建这个文件的权限,如果检查通过了,NameNode会为创建新文件写下一条记录,反之则会抛出一个异常:IOException
-
DistributedFileSystem向客户端返回一个FSDataOutputStream对象,这个样客户端就可以写入数据了,同样的这个对象会封装一个DFSOuptStream对象,它负责处理DataNode与NameNode之间的通信。在写数据时它会把数据分成一个一个数据包,并且写入内部队列,也就是数据队列(data queue)
-
DataStream处理数据队列,它负责选出适合用于存储数据副本的一组DataNode,并要求NameNode分配新的数据块。这一组DataNode会构成一条管线,DataStream会将数据包流式转输到管线中的第一个DataNode,然后依次存储并发送给下一个DataNode
-
DFSOutPutStream也维护着一个内部数据包队列来等待DataNode的收到确认回执,这个称为“确认队列”(ask queue),收到管线中所有DataNode确认信息后,这个数据包才会从确认队列删除
-
客户端完成数据的写入后,会对数据流调用close()方法
五、block副本的存放策略
HDFS中文件作为独立存储单元,被划分为块大小的多个块进行存储,同时HDFS为了保证容错性对于块需要自动保存多份副本(默认为三个副本),各个副本的存放策略简单介绍如下:
第一个副本:存放在上传文件的DN,如果是集群外提交的,则随机挑选一台磁盘空间更大,CPU更压力更小的DN存储
第二个副本:存放在与第一个副本不同的机架机点上
第三个副本:存放在与第二个副本相同的机架上
其它的副本:如果有其它的副本则随机节点存储