Hadoop学习笔记 - 02HDFS理论基础与读写流程

435 阅读6分钟

写在前面: 本文详细介绍了HDFS的存储模型、架构设计以及读写流程,作为Hadoop计算层分治和并行计算的核心,为后续介绍MapRedcue打下了基础。

存储模型

  • 文件线性按字节切割成块(block),block具有offsetid
  • 文件与文件的block大小可以不一样
  • 一个文件除了最后一个block,其他block大小一致
  • block的大小一句硬件的I/O特性调整
  • block被分散存放再集群的节点中,具有location
  • block具有副本(replication),没有主从概念,副本不能出现在同一个节点
  • 副本是满足可靠性和性能的关键
  • 文件上传可以指定block大小和副本数,上传后只能修改副本数
  • 一次写入多次读取,不支持修改(因为修改了其中的一个block,后续的block都要进行调整,并且还要重新分发至副本,会降低性能)
  • 支持追加数据

架构设计

  • HDFS是一个主从(Master/Slaves)架构
  • 由一个NameNode(主)和一些DataNode(从)组成,均为进程
  • 面向文件,包括文件数据(data)和文件元数据(metadata)
  • NameNode负责存储和管理文件元数据,并维护了一个层次型的文件目录树(虚拟目录结构)
  • DataNode负责存储文件数据(block块),并提供block的读写
  • DataNodeNameNode维持心跳,并汇报自己持有的block信息
  • ClientNameNode交互文件元数据和DataNode交互文件block数据

架构设计.png

block和datanode.png

上图中,在NameNode维护的元数据中保存了两个文件的文件名、副本数和blockid。文件part-0副本数为2,block id分别为1和3.文件part-1副本数为3,block id分别为2、4和5.在DataNode可以看到id为1和3的block会出现在2个DataNode中,id为2、4和5的block会出现在3个DataNode

角色功能

NameNode

  • 完全基于内存存储文件元数据、目录结构、文件block的映射(基于内存可以快速对外提供服务)
  • 需要持久化方案保证数据的可靠性(内存掉电易失、大小也有限制)
  • 提供副本防止策略

DataNode

  • 基于本地磁盘来存储block,并且会以文件的形式来存储(即,HDFS没有帮我们存数据,只做了管理映射的功能)
  • 并保存block的校验和(checksum),保证block的可靠性
  • NameNode保持心跳,汇报block列表状态

元数据持久化

  • 任何对文件系统元数据产生修改的操作,NameNode都会使用一种称为EditLog的事务日志记录下来
  • 使用FsImage存储内存所有的元数据状态
  • 使用本地磁盘保存EditLogFsImage
  • EditLog具有完整性,数据丢失少,但回复速度慢,并由体积膨胀风险(记录实时发生的增删改操作,体积小并且记录少时优势最大)
  • FsImage具有恢复速度快,体积与内存数据相当,但不能实时保存,数据丢失多(按照时间间隔将内存全量数据基于某一个时间点向磁盘溢写,更快地滚动更新时点时优势最大)
  • NameNode使用了FsImage + EditLog整合方案:
    • 滚动将增量的EditLog更新到FsImage,以保证更近时点的FsImage和更小的EditLog体积(和Redis的持久化也很类似)
    • 具体的方案可以是:假设NameNode在8点第一次开机的时候,只写一次FsImage,到9点的时候EditLog记录8-9点的日志,然后将8-9点的日志更新到9点的FsImage中,FsImage的数据时点就变成了9点。但是此时对于正常运行的NameNode来说没有任何作用,如果要达到持久化的好处,可以寻求另外一台机器来做。也就是SecondaryNameNode,后续会说。

HDFS启动时EditLogFsImage加载流程

  • HDFS搭建时会格式化,格式化操作会产生一个空的FsImage
  • NameNode启动时,从硬盘中读取EditLogFsImage
  • 将所有EditLog中的事务作用在内存中的FsImage
  • 并将这个新版本的FsImage从内存中保存到本地磁盘上
  • 然后删除旧的EditLog,因为这个旧的EditLog的事务已经作用在FsImage上了

安全模式

  • NameNode启动后会进入一个称为安全模式的特殊状态,处于安全模式的NameNode不会进行数据块的操作
  • NameNode从所有的DataNode接收心跳信号和数据块状态的报告
  • 每当NameNode检测确认某个数据块的副本数目达到最小值,那么该数据块会被认为时副本安全的(safekt reokucated)
  • 在一定百分比(可配置)的数据块被NameNode检测确认时安全后,并且等待额外的30s后,NameNode将会推出安全模式
  • 接下来它会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他DataNode

SecondaryNameNode(SNN)

  • 在非HA模式下,SNN一般时独立的节点,周期完成对NameNodeEditLogFsImage合并,减少EditLog大小,减少NameNode启动时间
  • 根据配置文件中的fs.checkpoint.period设置时间间隔,默认3600秒
  • 根据配置文件中的fs.checkpoint.size设置EditLog大小,规定EditLog文件最大值默认为64M

secondary namenode.png

Block副本防止策略

  • 第一个副本:放置在上传文件的DataNode,如果是集群外提交,则随机挑选一台磁盘不太满、CPU不太忙的节点
  • 第二个副本:放置在与第一个副本不同的机架节点上
  • 第三个副本:与第二个副本相同机架的节点
  • 更多副本:随机节点

HDFS写流程

写流程.png

  • 客户端找与NameNode建立连接,并创建元数据。NameNode判断元数据是否邮箱,触发副本放置策略告诉客户端一个有序的DataNode列表
  • 客户端与最近的DataNode建立tcp连接,第一个DataNodeDataNode建立tcp连接,后面以此类推。(pipeline of datanodes)
  • 客户端将block切成64k的packet(并用512b的chrunk+4b的chunksum和,即共516b的数据来填充)传给第一个DataNode,第一个DataNode内存存一份磁盘存一份,第一个DataNode再将数据传给第二个DataNode,同时客户端将第二个block传给第一个DataNode,以此类推。流式也是变种的并行。
  • 当一个block传输完成,则客户端继续向NameNode申请传输第二个block
  • HDFS使用这种传输方式,副本数对于客户端时透明的。当block传输完成,DataNode各自向NameNode进行汇报,同时客户端继续传输下一个block。所以客户端的传输和block的汇报也是并行的

HDFS读流程

读流程.png

  • 客户端找与NameNode建立连接,获取block信息
  • 从距离客户端近的DataNode建立连接(本机、本机架、其他机架副本),DataNode读取block并进行返回
  • 客户端尝试下载block并校验数据完整性

HDFS支持客户端给出文件的offset自定义连接哪些blockDataNode,自定义获取数据。这是支持计算层的分治、并行计算的核心。