HDFS架构原理和读写流程分析,数据完整性,HA,fsimage,editlog

HDFS全称为Hadoop Distributed File System,是hadoop分布式文件系统的简称,也是hadoop的核心。数据最小存储粒度按照块存储。hdfs是一次写入,多次读取,可以追加数据但是无法修改数据。
hdfs集群是Master/Slave结构

在HDFS中主要有如下几个角色: NameNode,DataNode,SecondaryNameNode,Client

  • NameNode namenode在hdfs中相当于master的角色,负责管理文件系统的命名空间,以及数据块到具体datanode节点的映射信息。namenode会响应客户端的读写请求然后指导DataNode处理实际文件读写。NameNode的作用主要有两个:
  1. 维护文件系统的命名空间,即文件系统的目录树、元数据等信息,目录树中维护中文件与数据块的对应关系,都是交由namedoe管理的
  2. 数据块和数据节点管理,hdfs中冗余备份是在数据节点上的,namenode维护者数据块与数据节点之间的关系,主要有:(1)数据块存在在哪些节点上 (2)一个数据节点上保存了哪些数据块
  3. 客户端对文件操作的支持。 客户端写入、追加、读取都需要先和namenode通信取得相关信息
  • DataNode DataNode中以块的形式保存数据,同时还会响应客户端的读、写数据块的请求。另外DataNode会周期性向NameNode上报心跳信息、数据块信息,DataNode实际的作用有两个
  1. 实际存储块数据
  2. 执行客户端的实际读取、写入
  • Client 主要作用有:
    1)上传文件时按照block大小对文件进行切分
    2)和NameNode交互,获取文件的元数据信息
    3)和DataNode交互,读取和写入文件

SecondaryNameNode、fsimage、editlog

我们知道在NameNode中,元数据信息是被缓存在内存中的,一旦NameNode宕机,那么内存中的数据将全部丢失,我们必须能够将这些重要的元数据信息持久化保存,并且不丢失能够在NameNode重启时重建命名空间。在NameNode中,命名空间记录在fsimage中,fsimage中每个文件或目录信息保存为一条记录,NameNode在重启时会读取fsimage来重构命名空间。
但是fsimage是磁盘文件,我们不能每次有修改都立马写入fsimage文件,这会让NameNode运行缓慢,因此hdfs中会间隔一段时间更新fsimage。而在这段时间内,hdfs会将相关更新写入到editlog中,然后会按照时间维度和空间维度将editlog合并到fsimage中(hdfs会按照一定间隔时间合并,但是当editlog达到一定大小的时候也会进行合并)

NameNode只会在启动的时候会合并fsiamge和editlog,运行期间合并fsimage和editlog是交由SecondaryNameNode来进行处理的

HDFS文件写入

在说文件写入之前,我们需要对相关文件大小进行说明

  • block 众所周知,hdfs文件的基础单元是block,一般为64M或128M,hdfs中是按照block进行分布式存储的,写入数据的时候,客户端会将文件按照block大小进行拆分
  • packet 是客户端项DataNode写入数据的基本单元,客户端并不是每次写一个block大小,而是每次通过网络传输写入一个packet大小,默认是64KB,dfs.write.packet.size配置
  • chunk 是客户端写入DataNode时校验的基本单元,默认大小是512B,io.bytes.per.checksum配置。客户端每写入512B大小的数据,会产生对应4B大小的校验数据,chunk写入packet的大小是516B,数据与校验大小比为128:1
    写请求流程:
  1. 客户端向NameNode发送写文件请求,NameNode经过各种判断后,如果没有问题会返回客户端一个FSDataOutputStream
  2. 客户端按照block切分文件,FSDataOutputStream会将数据按照packet进行切分,并放入dataQueue中
  3. FSDataOutputStream向NameNode申请DataNode来存储当前block,如果副本数是3,会将这个三个datanode排成一个队列,然后向d1中写入一个packet,d1在向d2写入,d2在向d3写入,形成一个流式操作。在写入一个packet之后会将其放入到ackqueue中,d3写成功之后返回d2,d2写入成功返回d1,d1写入成功在返回客户端,客户端在从ackequeue中移除这个packet
  4. 在一个block大小的数据写完之后,客户端会关闭写入流,DataNode会将内存中的数据写入磁盘中,持久化数据,并发送信息给NameNode

HDFS文件读取

  1. 客户端向NameNode申请获得文件的信息,主要是文件块信息,返回客户端block地址信息
  2. 客户端根据地址信息按照hadoop拓扑结构就近读取对应block数据
  3. 读取完一个block之后会对其进行chucksum校验(校验每个块的信息通过偏移量和预写值对比,写的时候是校验packet的信息),如果读取 DataNode 时出现错误,客户端会 通知 NameNode,然后再从下一个拥有该 block 拷贝的 DataNode 继续读
  4. 读取完一个block之后会继续读下一个,知道所有的都读取完,

HDFS文件系统的有点:
采用简单一致性,一次写入多次读取,不能修改数据但是可追加数据
高容错,低成本:可以搭建在廉价的机器上,并且数据以多副本保存在不同的服务器上,某个副本丢失,也能通过别的副本进行恢复;
流式数据访问:不是随机读写;
适合大规模数据集:能够进行批处理,支持横向扩展,支持PB级数据和10k节点规模
缺点:

延迟高:不支持低延迟数据访问,做不到毫秒级存储数据,但是适合高吞吐率(某一时间内写入大量的数据)的场景;
不适合小文件:每条元数据占用空间是一定的,因此大量小文件会占用NameNode大量的内存来存储文件、目录和块信息;
不支持并发写入:一个文件只允许一个线程进行写操作,不适合并发写入;
不能修改和随机读写:文件不允许修改,只支持追加,同时也不是随机读写。

猜你喜欢

转载自blog.csdn.net/LeoHan163/article/details/116863357