管网:https://hadoop.apache.org/

核心模块

The project includes these modules:
  • Hadoop Common: The common utilities that support the other Hadoop modules.
  • Hadoop Distributed File System (HDFS****): A distributed file system that provides high-throughput access to application data.
  • Hadoop YARN: A framework for job scheduling and cluster resource management.
  • Hadoop MapReduce: A YARN-based system for parallel processing of large data sets.

下面开始逐步学习HDFS,其中包含如下知识点:

  • 存储模型
  • 架构设计
  • 角色功能
  • 元数据持久化
  • 安全模式
  • 副本放置策略
  • 读写流程
  • 安全策略

存储模型

下面这几点,死记硬背,基本常识

  • 文件线性按字节切割成块(block),具有offset,id

在计算机当中无论你是啥文件,图片、视频、音频等,最终储存的都是二进制位,一般计算机中描述文件用的基本都是字节,一个字节=8个二进制位,换言之,只要是文件就是一个字节数组

  • 文件与文件的block大小可以不一样
  • 一个文件除最后一个block,其他block大小一致

比如一个稳健,26个直接,按4个字节切块,切6块后,剩下的2个字节就是单独的一块。所以,除了最后的一块不一样之外,其他的块的大小都是一样的

  • block的大小依据硬件的I/O特性调整

在 1.x的版本64M是其默认块大小,2.x版本的时候是128M为默认块大小,后续高版本的时候是256M,具体就是根据硬件的特性来决定

  • block被分散存放在集群的节点中,具有location

文件被切成块之后,如果你有几十上百台机器,可以把这些块打散在不同的机器上节点上,具有location就是块在哪个节点上要记录下来

  • block具有副本(replication),没有主从概念,副本不能出现在同一个节点

就是说有几个副本就是在几个节点上,没有说是几个主分片,几个副本的,这个要与ES中的分片概念区分下,副本在不同节点就是为了解决容灾的问题

  • 副本是满足可靠性和性能的关键
  • 文件上传可以指定block大小和副本数,上传后只能修改副本数
  • 一次写入多次读取,不支持修改
  • 支持追加数据

架构设计

官网文档地址:http://apache.github.io/hadoop/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html

  • HDFS是一个主从(Master/Slaves)架构
  • 由一个NameNode(主)和一些DataNode(从)组成
  • 面向文件包含:文件数据(data)和文件元数据(metadata)

文件数据就是文件本身;文件元数据就是文件的属性,作者、日期、权限、持有者…和文件内容无关的东西

  • NameNode负责存储和管理文件元数据,并维护了一个层次型的文件目录树
  • DataNode负责存储文件数据(block块),并提供block的读写
  • DataNode与NameNode维持心跳,并汇报自己持有的block信息
  • Client和NameNode交互文件元数据和DataNode交互文件block数据

一、Hadoop - HDFS理论基础读写流程 - 图1

一、Hadoop - HDFS理论基础读写流程 - 图2

角色功能

NameNode

  • 完全基于内存存储文件元数据、目录结构、文件block的映射
  • 需要持久化方案保证数据可靠性
  • 提供副本放置策略

DataNode

  • 基于本地磁盘存储block(文件的形式)
  • 并保存block的校验和数据保证block的可靠性
  • 与NameNode保持心跳,汇报block列表状态

元数据持久化

常规的数据持久化形式:

  1. 日志文件:记录实时发生的操作,比如增删改查等,mkdir /abc append 文本文件
    优点:完整性比较好
    缺点:加载恢复数据慢、占空间

比如说,我机器内存4G,运行了10年,记录了大量的日志文件,突然有一天机器坏了,需要恢复数据,5年?内存会不会溢出?思考下

  1. 镜像、快照、dump、db 、序列化

    1. 间隔(小时、天、10分钟、1分钟、5秒钟),内存全量数据基于某一个时间点做的向磁盘的溢写
    2. 优点:恢复速度快过二进制文件
    3. 缺点:间隔写入的,容易丢失部分数据 ,还会占用大量的I/O频繁全量去写

问题!!!

如果 999999999存储下来占用多大的磁盘空间?

以什么文件编码来存储?

文件编码:txt byte 9个字节 可以直接打开看到对应的文本数据

int a = 999999999 占用4个字节 序列化成二进制字节数组就无法打开直接查看

HDFS的持久化方式:

EditLog 日志文件:如果记录的文件体积小,记录少,就有优势

FsImage 镜像(快照):如果能更快的,滚动的更新时点,就是到某个时间点就生成一个全量数据的快照

恢复过程:

最近时点的FsImage + 增量的EditsLog

假设现在11点,恢复过程:

FI 9点前的+ 9点到10点的增量的EL

1、加载FI

2、加载EL

3、内存就得到了关机前的全量数据

问题:FI 时点是怎么滚动更新的?

由 NN(NameNode) 8点溢写,9点溢写。

NN:第一次开机的时候,只写一次FI ,假设8点,到9点的时候,EL 记录的是8~9的日志,NN只需要将8~9的日志的记录,更新到8点的FI中,FI的数据时点就变成了9点!但是这种方式有点多此一举,分散NN的职能,FI还不如直接到点重新生成一个,所以就需要寻求另外一台机器来做这个合并的事情:

SecondaryNameNode(SNN):

  • 在非Ha(high availability)模式下,SNN一般是独立的节点,周期完成对NN的EditLog向Fslmage合并,减少EditLog大小,减少NN启动时间
  • 根据配置文件设置的时间间隔fs.checkpoint.period 默认3600秒
  • 根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB

一、Hadoop - HDFS理论基础读写流程 - 图3

SecondaryNameNode职责

帮助nn 把最近的edit.log日志文件合并到fismage文件当中,清空一下日志 得到一个新的fsimage文件

snn checkpoint机制

1、首先建立一个eits.new用来记录后续执行的日志文件

2、snn拉取之前的eits 日志文件和fsimage文件

3、snn 把拉取的eits日志和fsimage文件加载到内存当中并做合并操作

4、把合并完的内容存储到fsimage.ckpt中

5、把fsimage.ckpt 跟之前的fsimage 做一个校检作为最新的fsimage,原有的保留以供数据恢复使用

真实企业中是不使用这种模式的,因为里面只有一个NN,如果挂了整个业务的客户端就下线了。了解即可

小结

  • 任何对文件系统元数据产生修改的操作,Namenode都会使用一种称为EditLog的事务日志记录下来
  • 使用Fslmage存储内存所有的元数据状态
  • 使用本地磁盘保存EditLog和FsImage
  • EditLog具有完整性,数据丢失少,但恢复速度慢,并有体积膨胀风险
  • Fslmage具有恢复速度快,体积与内存数据相当,但不能实时保存,数据丢失多
  • NameNode使用了Fslmage+EditLog整合的方案,滚动将增量的EditLog更新到Fslmage,以保证更近时点的Fslmage和更小的EditLog体积

安全模式

  • HDFS搭建时会格式化,格式化操作会产生一个空的Fslmage
  • 当Namenode启动时,它从硬盘中读取Editlog和Fslmage
  • 将所有Editlog中的事务作用在内存中的Fslmage上并将这个新版本的Fslmage从内存中保存到本地磁盘上
  • 然后删除旧的Editlog,因为这个旧的Editlog的事务都已经作用在Fslmage上了
  • Namenode启动后会进入一个称为安全模式的特殊状态
  • 处于安全模式的Namenode是不会进行数据块的复制的
  • Namenode从所有的 Datanode接收心跳信号和块状态报告
  • 每当Namenode检测确认某个数据块的副本数目达到这个最小值,那么该数据块就会被认为是副本安
  • 全(safely replicated)的在一定百分比(这个参数可配置》的数据块被Namenode检测确认是安全之后(加上一个额外的30秒等待时间),Namenode将退出安全模式状态
  • 接下来它会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他Datanode上

副本放置策略

我们上面已经提到块都是有副本的概念的,下面聊下块的副本的放置策略

  • 第一个副本:放置在上传文件的DN的节点,第一个副本写入本地文件速度最快;如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点
  • 第二个副本:放置在于第一个副本不同的机架的节点上
  • 第三个副本:与第二个副本相同机架的节点
  • 更多副本:随机节点

读写流程(面试必问)

写流程

假设一个很大的文件按照64M一块的切分策略,下面详细的记录一块的写入流程

数据单位:

block :文件上传前需要分块,这个块就是block,一般为128MB,可以修改。因为块太小:寻址时间占比过高。块太大:Map任务数太少,作业执行速度变慢。它是最大的 一个单位。 packet :packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。 chunk :chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte 的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值 约为128 : 1。(即64*1024 / 512)

一、Hadoop - HDFS理论基础读写流程 - 图4

  1. 首先客户端Client向NN(NameNode)发出写文件请求,Client和NN建立连接交换文件元数据
  2. NN判定元数据是否有效,如果校验通过继续,否则就打回
检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。 (注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续内存操作失败了,EditLog中有记录也方便恢复)
  1. NN触发副本放置策略,返回一个有序的DN列表给到Client
  2. Client和DN建立TCP连接,进行pipeline流式传输

Client只和第一个DN建立TCP连接,第二个DN和第一个DN建立TCP链接,第三个DN和第二个DN建立TCP链接,以此类推

  1. Client将块切分成packet (64KB),并使用chunk (512B) +chucksum (4B)填充

Client 在写入块的时候并不是一次性传输 64M或者128M,而是先创建一个buffer的packet包,默认是 64KB,然后每次从大块上面读取更小的单位chunk,每次读取 一个chunk (512B) +chucksum (4B)来填充64KB的packet,直到达到 64KB这个包就准备好了,然后发送到队列dataqueue中,这种传输的速率极高,只需要考虑第一个节点传输写入的时间就行了,不需要过多考虑副本的数量对传输时间的影响

  1. Client将packet放入发送队列dataqueue中,并向第一个DN发送
  2. 第一个DN收到packet后本地保存并发送给第二个DN
  3. 第二个DN收到packet后本地保存并发送给第三个DN
  4. 这一个过程中,上游节点同时发送下一个packet
  5. 生活中类比工厂的流水线:结论:流式其实也是变种的并行计算
  6. Hdfs使用这种传输方式,副本的数量对于client是透明的
  7. 当block传输完成,DN们各自向NN汇报,同时client继续传输下一个block
  8. 所以,client的传输和block的汇报也是并行的

如果传输过程中某一个DN节点挂了怎么处理?

如果传输过程中DN副本挂了,NN就收不到其中某个的DN心跳包,Client会立即跟其他的DN建立连接,进行数据的比对补全和传输,同时副本数量不足,NN内部会有一个策略让DN内部再复制出一个节点出来

读流程

一、Hadoop - HDFS理论基础读写流程 - 图5

  • 为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本
  • 如果在读取程序的同一个机架上有一个副本,那么就读取该副本
  • 如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本
  • 语义:下载一个文件
    • Client和NN交互文件元数据获取fileBlockLocation
    • NN会按距离策略排序返回
    • Client尝试下载block并校验数据完整性
  • 语义:下载一个文件其实是获取文件的所有的block元数据,那么子集获取某些block应该成立
    • Hdfs支持client给出文件的offset自定义连接哪些block的DN,自定义获取数据
    • 这个是支持计算层的分治、并行计算的核心

提问:分布式文件系统那么多,为什么hadoop项目还有开发一个hdfs文件系统?

因为hdfs文件系统可以暴露块的位置信息,支持客户端读取文件的任意位置,最终实现对文件的并行计算,这就是分布式文件系统hdfs文件系统的优势