HDFS是什么 ?

发布时间 2023-07-04 14:50:39作者: 等不到的口琴

HDFS是什么 ?

我们先简单回顾下《大数据解决什么问题 ?》中对分布式计算的简单介绍,对于一批数据,我们先需要将其分割分块分配到不同的机器上,同时将我们的计算程序分发给这些机器,让这些机器将其存储的数据按照我们的计算逻辑进行Map映射、Reduce计算,然后汇总后返回数据集。

上面是初步的hadoop进行数据存储以及数据计算的过程,而HDFS主要负责的就是将一个大数据量的data分成相等的块(block)分发给不同的NameNode

既然涉及数据切割、分发、上传,读数,那么就需要关注数据切割是否会损坏,分发策略、上传策略以及读数据写数据的流程。这儿先讲读数据的流程,需要说明的是这儿只是为了便于理解初步讲解,后面会讲解详细流程,现在有一个集群, 里面有很多机器,这些机器的特色是单台机器性能并不高,但是好处是可以并行处理一些任务,现在有一批原始数据 ,客户端想做统计出相同的内容的条数,那么现在先与集群管理者NameNode(后面简称NN)沟通,告诉NN我有一个需要计算的任务,数据量为1TB,接下来NN会根据目前集群的情况做一个权衡,然后告诉客户端你先将这些数据存储到我们的集群上,于是返回一些存储有关的元数据信息例如数据会被存储在哪些节点(DataNode、后面简称DN)给客户端,然后客户端与集群链接将数据进行存储,然后集群反馈NN存取的确认信息,至此,HDFS职责就完成了,但是上述流程会存在一些问题:

1、NN维护了集群文件与所在DN的映射关系(元数据),内存特点是掉电易失,也就意味着要落盘备份 ==> 引入了日志备份FSImage、EditLog

2、NN节点可能会挂 ==> 也就涉及主备集群,确保即使NN挂了也能对外提供服务

3、 集群需要领导 ==> 引入zookeeper进行选举

3、选举后新节点为了恢复数据,需要先读取FSImage, 然后整合EditLog ==> 这个操作会很耗时,意味着还是可能不可用,引入SecondaryNameNode(SNN)辅助进行日志合并

4、block到达DN集群后,可能存在某个块被损坏无法读取从而影响整体文件的可读性 ==> 数据彼此备份,这儿就涉及一个副本备份策略。

DataNode

我们需要理解的是,HDFS是基于JAVA语言开发的,角色需要进行资源管理, 那么角色对应虚拟机的一个进程,我们通常说一个集群有1000台机器,这1000通常是指DN的数量,并且这个节点是一台完善的计算机,包含操作系统等,而DataNode主要就是为了存储数据被分割后的块,理论上来讲,除了NameNode外都会包含一个DataNode程序,如果一个DataNode 需要将被分配的block写进磁盘, 那么需要交由节点的kernel写入,这也就意味着HDFS并不关心数据的存储,只是做了数据的映射。

DataNode除了在本地存储数据块,还需要保存block的校验和数据, 保证可靠性,同时要与NameNode保持心跳,时刻反馈自己的存活状态,以便于NameNode有最新且可用的映射关系。

NameNode

阿里要求一个集群机器数量不要超过两千, 这个两千是指DN的数量, NN在一个HDFS中只有一个,基于此,为了保证NN的响应速度,那么元数据(映射关系)就需要基于全内存,万一断电或者需要服务重启数据就会丢失, 那么就需要对内存数据的持久化,数据持久化通用策略有两个:

基于快照:隔段时间备份一次,如数据库的备份、Redis的RDB等,优点是节省空间,恢复相对于基于命令的会更快,缺点是可能会丢失一个时间差大数据。

基于命令:每秒钟用日志命令追加,优点是数据不会丢,但是持续运行一段时间之后,如果不做处理这个文件极大,不便于数据恢复。

所以一般的持久化策略就是基于快照与基于命令结合的方式,HDFS也采取了FsImage (基于快照)+ EditLog(基于命令)的持久化方式

具体策略是:滚动将增量的EditLog更新合并到FsImage,以保证最近时点的FsImage和最小体积的EditLog

元数据持久化

  • 任何对文件系统元数据进行修改的行为都会被Editlog的事务日志记录下来
  • 使用FSImage存储内存所有元数据的状态
  • 使用本次磁盘保存Editlog和FsImage
  • Editlog具有完整性,数据缺失少,但是恢复速度很慢,并且具备体积膨胀的风险
  • FsImage具备恢复速度快,体积与内存数据体积相当,但不能实时保存,丢失数据多
  • NN采用的FS+EditLog结合的形式,滚动的将Editlog更新整合进FsImage ===> 消耗NN的IO,可能导致响应不及时,为此引入的SNN

SecondaryNameNode

由于NN全局只有一个,需要每时每秒对外提供服务,性能压力较大,而这个日志合并又是频繁的IO操作,负担较重,于是考虑将这部分性能压力分担给另外一个号节点SecondaryNameNode(后面简称 SNN),SNN负责将产生的EditLog合并进FsImage

在非HA模式下,SNN一般是独立的节点,周期完成对NN的EditLog向FsImage合并的操作

根据配置文件设置间隔时间fs.checkpoint.period 3600秒设置日志大小fs.checkpoint.size 最大64M

安全模式

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

NameNode启动之后会进入一个称为安全模式的特殊状态,处于这个模式的NameNode

  1. 不会进行数据块的复制
  2. 从所有的DataNode中接受心跳和块状态报告
  3. 当确认数据块的副本数达到安全值(人为设定,最小三个)时就默认该数据块是副本安全的
  4. 在一定百分比(这个参数可以配置)的数据块被NN检测到是安全的之后,加一个额外的30等待时间,NN将退出安全模式
  5. 接下来会确定没有达到安全的数据块数目,并进行安全性复制。

NN存储数据块会包含两方面的信息,其一是元数据(文件属性,例如路径,多大,名称、持有者、rwxrwxrwx等),其二是存储在那个DN上,持久化时只持久化元数据而不持久化存储的位置,潜在的风险:NN会丢失块的位置信息====> 重启后,由于较长时间没有与DN建立心跳,有可能DN已经损坏,即提供给客户端的数据是不准确的,所以安全模式期间同DN进行心跳检测。

存储模型

  • 文件按照线性进行切割,具有offset、id
  • 文件与文件block大小可以不一样,块大小设置最初是64M但后来随着计算机读取速度的提升,默认为128M,可以自己调整,但所有block大小相同
  • block大小根据机器的硬件性能确定
  • block分散在集群的节点中,具有location ====> 知道块在哪儿,即地址
  • Block具有副本(replication), 但没有主从的概念,副本不可能出现在同一个节点中 ====> 如果说一个文件具有三个副本,意味着有几个块?
  • 副本是满足可靠性与性能的关键 ====> 副本放置策略,性能是指多任务并行计算可以取不通的块
  • 文件上传可以指定block的大小,但是上传之后只能修改副本数
  • 一次写入多次读取,不支持修改 ====> 为啥不支持修改 ? 泛洪操作
  • 支持追加数据

架构设计

  • HDFS是一个主从的架构
  • 由一个NameNode和一些DataNode组成
  • 面向文件包括:文件数据、文件元数据
  • NameNode负责存储管理文件元数据,并且维护了一个层次分明的文件目录树
  • DataNode负责存储文件的数据块(block),并且提供块的读写
  • DataNode与NmaeNode维持着心跳,并且汇报自己的块信息
  • Client与NN交换元数据信息,与DN交互文件数据

角色即进程,意味着NN里面的虚拟机维护着目录树/home/courage/data1/,文件路径全局唯一

副本放置策略

副本放置策略,是同一个块的副本,不是一个文件的所有块。

  • 第一个副本与DN在相同的服务器上
  • 第二个副本一定要出服务器机架,这在1.X时还没有这个要求,即1.X版本副本2可以与副本1位于同一个机架 ==> 原因是可能将副本策略设置为2
  • 第三个副本与第二个副本相同的机架
  • 其余的副本则随便放

HDFS写流程

  • Client与NN连接创建文件元数据
  • NN判定元数据是否有效
  • NN触发副本放置策略,返回一个有序的的DN列表
  • Client与DN列表里面的第一个DN建立Pipeline连接
  • 将块(block)切割成更小的packet(64kb), 并且使用chunk(512b) + chucksum(4b)进行填充
  • Client将切割后的packet放入发送队列dataqueue中,并向第一个DN发送数据
  • 第一个DN收到packet后本地保存并且发送给第二个DN
  • 第二个DN收到packet后本地保存并且发送给第三个DN
  • 这个过程期间上游同时发送第二个packet=====> 这是变相的并行计算
  • HDFS这种传输模式,副本对于Client是透明的
  • 当block传输完成,DN们各自向NN汇报,同时Client继续传输下一个block,即client传输与block汇报也是并行的。

HDFS读流程

读流程:

客户端向NN申请取XX文件,NN会根据距离返回一个各个block所在的DN列表,然后Client根据最小距离去取block

思考:如果可以下载所有的block拼接成一个完成的文件,那么是不是也可以不下载所有的块?

hdfs可以暴露所有块的位置以及偏移量,意味着可以读想读的块。

  • 为了降低整体的宽带消耗和读取延时,HDFS会尽量让读取程序读取离他距离近的副本

  • 如果在读取程序的同一个机架上有一个副本,那么就读取该副本

  • 如果HDFS就集群横跨多个数据中心,那么客户端也将首先读取本地数据中心的副本。

  • 语义:下载一个文件

  • Client 和NN 交互文件元数据获取fileBlockLocation

  • NN根据距离策略排序返回

  • Client尝试下载block并且校验数据完整性

  • 那么,获取这些block子集应该成立 => 实际上 HDFS支持Client给出文件的offset自定义链接哪些Block的DN,自定义获取数据==> 这是支持计算分治、并行计算的核心。