大数据相关博客的目录

HDFS概述

HDFS诞生背景

随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。

HDFS是分布式文件管理系统中的一种。

HDFS的定义

HDFS(Hadoop Distributed File System),它是一个文件系统,用于存储文件,通过目录树来定位文件。
它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
HDFS适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。

HDFS的优缺点

优点:

  • 高容错性
    • 数据自动保存多个副本,通过增加副本的形式,提高容错性。
    • 某一个副本丢失以后,它可以自动恢复。
  • 适合处理大数据
    • 数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据。
    • 某一个副本丢失以后,它可以自动恢复。
    • 文件规模:能够处理百万规模以上的文件数量,数量相当之大。
  • 低成本
    • 构建在廉价机器上,通过多副本机制,提高可靠性。

缺点:

  • 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
  • 无法高效的对大量小文件进行存储。
    • 存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
    • 小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
  • 不支持并发写入、文件随机修改。
    • 一个文件只能有一个写,不允许多个线程同时写;
    • 仅支持数据append(追加),不支持文件的随机修改。

HDFS架构

1hdfs架构

NameNode(nn)

NameNode是所有HDFS元数据的仲裁者和管理者。数据永远不流过NameNode。

功能:

  • 管理HDFS的命名空间
  • 配置副本策略
  • 管理数据块(Block)映射信息
  • 处理客户端读写请求

DataNode

NameNode下达命令,DataNode执行实际的操作。

功能:

  • 存储实际的数据块;
  • 执行数据块的读/写操作。

Client:

客户端。

功能:

  • 文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
  • 与NameNode交互,获取文件的位置信息;
  • 与DataNode交互,读取或者写入数据;
  • Client提供一些命令来管理HDFS,比如NameNode格式化;
  • Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;

Secondary NameNode(2nn)

功能:

  • 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode。
  • 在紧急情况下,可辅助恢复NameNode。

但是2nn并非nn的热备。当nn挂掉的时候,它并不能马上替换NameNode并提供服务。

【面试重点】HDFS 文件块大小

HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中是64M。

在HDFS中,由于文件是通过文件块(block)存储的,因此在传输文件时需要进行寻址。通常寻址的时间为10ms左右。
当寻址时间为传输时间的1%时,为最佳状态,即传输时间约为1秒。
目前磁盘的传输速率普遍为100M/s左右,因而每一个文件块的大小被规定为128MB。

【面试重点】为什么HDFS不适合存储小文件

  1. 在HDFS中,因为NameNode需要将文件系统的元数据存放在内存当中,因此存储的文件数目受限于NameNode的内存大小。HDFS中每个文件、目录以及数据块所占用的空间是150B,如果存放大量的小文件,可能会导致元数据占用的内存空间和文件占用的磁盘空间比例较大,占用较高的内存。
  2. HDFS适用于高吞吐量,不适合低时间延迟访问。同时存入大量小文件会花费很长时间。
  3. 文件过小会导致寻址时间较长,传输时间较短,不符合HDFS的设计。

【面试重点】HDFS数据流

HDFS写数据流程

2hdfs写文件

  1. 客户端通过分布式文件系统向NameNode发起上传文件请求,NameNode检查目标文件是否存在、父目录是否存在
  2. NameNode返回是否允许上传
  3. 客户端请求第一个Block上传到哪几个服务器上
  4. NameNode返回x个DataNode节点,分别为DataNode1、DataNode2、...
  5. 客户端请求DataNode1上传数据,DataNode1收到请求后会继续调用DataNode2、...,将这个通信管道建立完成
  6. DataNode1、DataNode2、...逐级应答客户端
  7. 客户端往DataNode1上传第一个Block,先从磁盘读取数据放到一个本地内存缓存,以Packet为单位,DataNode1收到一个Packet就会传给DataNode2,...;DataNode1每传一个Packet就会放入一个应答队列等待应答。
  8. 当一个Block传输完成后,客户端再次请求NameNode上传第二个Block服务器,重复执行3-7

在这个过程中,客户端与服务器的上传只有将本地文件上传到DataNode1的过程,DataNode1传递给其他节点是通过服务器之间按照顺序传输。

网络拓扑 - 节点距离计算

在HDFS写数据的过程中,为了节省资源开销,NameNode会选择距离带上传数据最近距离的DataNode接收数据。
这个距离被成为节点距离,其大小为两个节点到达最近的共同祖先的距离总和。

3网络拓扑

节点距离计算案例:

  • Distance(/d1/r1/n0, /d1/r1/n0)=0:表示同一机架上的同一节点上的进程,其节点距离为0
  • Distance(/d1/r1/n1, /d1/r1/n2)=2:表示同一机架上的不同节点,n1n2的共同祖先是机架r1n1r1的距离为1,n2到r1的距离为1,总和为2
  • Distance(/d1/r1/n0, /d1/r2/n0)=4:表示同一集群中心不同机架上的两个节点,/r1/n0/r2/n0的共同祖先是/d1,从/r1/n0/d1的距离为2(n0r1为1,r1d1为1),从/r2/n0/d1的距离为2,总和为4
  • Distance(/d1/r1/n0, /d2/r1/n0)=6:表示同一数据中心不同集群中心的两个节点,/d1/r1/n0/d2/r1/n0的共同祖先是数据中心,从/d1/r1/n0到数据中心的距离为3,从/d2/r1/n0到数据中心的距离为3,总和为6

【正在学习】机架感知

【正在学习】副本放置策略

HDFS读数据流程

4hdfs读文件

  1. 客户端通过分布式文件系统向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
  2. 挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
  3. DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
  4. 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

【面试重点】HDFS数据存储策略

前置概念介绍

  • 元数据:在文件上传到HDFS服务器的时候,会被分成多个块,并以多副本的形式存储在服务器上面,元数据是用来记录该文件的文件名、被分成了多少块、每个块存储在哪些服务器中的信息。
  • Fsimage:NameNode内存中元数据序列化后形成的文件。
  • Edits:记录客户端更新元数据信息的每一步操作,即日志。可通过Edits运算出元数据。

NameNode和SecondaryNameNode工作机制

在HDFS的场景下,因为需要经常进行随机访问,还要相应客户端请求,为了提高效率,元数据需要存放在内存当中。

然而在实际的开发场景中,断电和宕机也是需要考虑在内的,而一旦发生,内存将会全部丢失,这样的话,整个集群就无法正常工作了。因此元数据需要备份到磁盘中,于是产生了FsImage

当元数据更新时,如果同时更新FsImage,就会导致效率过低,但是如果不实时更新就会引发一致性问题,一旦NameNode节点内存故障或断电,就会有部分数据是会丢失的。
因此又引入了Edits文件,该文件只进行效率较高的追加操作。每当元数据有更新或者添加元数据时,内存中的元数据修改,并追加到Edits中。这样,即使NameNode断电,也可以通过FsImagesEdits的合并,合成元数据。

但是如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据的时间会过长。为了解决这个问题,需要定期对FsImagesEdits进行合并。然而如果这个操作由NameNode节点完成,势必会增加NameNode的压力,降低效率。因此引入了一个新的节点——SecondaryNameNode,专门用于FsImagesEdits的合并工作。

5nn和2nn工作机制

工作机制:

  • 第一阶段:NameNode启动
    1. 第一次启动NameNode格式化后,创建FsImageEdits文件。如果不是第一次启动,则直接加载FsImagesEdits到内存。
    2. 客户端对元数据进行增删改的请求
    3. NameNode记录操作日志,更新滚动日志
    4. NameNode在内存中对数据进行增删改
  • 第二阶段:SecondaryNameNode工作
    1. SecondaryNameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查的结果。
    2. SecondaryNameNode请求执行CheckPoint。
    3. NameNode滚动正在写的Edits日志。
    4. 将滚动前的EditsFsImages文件拷贝到SecondaryNameNode
    5. SecondaryNameNode加载EditsFsImages文件到内存并合并。
    6. 生成新的镜像文件fsimage.chkpoint
    7. 拷贝fsimage.chkpoint到NameNode。
    8. NameNode将fsimage.chkpoint重新命名成fsimage

EditsFsImages存放在HADOOP_NAME_DIR下的current文件夹中:

6edits和fsimages

NameNode启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载EditsFsimage到内存中,此时 NameNode 内存就持有最新的元数据信息。
Client 开始对 NameNode 发送 元数据的增删改的请求,这些请求的操作首先会被记录到 edits.inprogress 中(查询元数据的操作不会被记录在 Edits 中,因为查询操作不会更改元数据信息),如果此时 NameNode 挂掉,重启后会从 Edits 中读取元数据的信息。然后,NameNode 会在内存中执行元数据的增删改的操作。
由于 Edits 中记录的操作会越来越多,Edits 文件会越来越大,导致 NameNode 在启动加载Edits 时会很慢,所以需要对 EditsFsimage 进行合并(所谓合并,就是将 EditsFsimage加载到内存中,照着 Edits 中的操作一步步执行,最终形成新的 Fsimage)。
SecondaryNameNode 的作用就是帮助 NameNode 进行 EditsFsimage 的合并工作。
SecondaryNameNode 首先会询问 NameNode 是否需要 CheckPoint(触发 CheckPoint 需要 满足两个条件中的任意一个,定时时间到和 Edits 中数据写满了)。直接带回 NameNode 是否检查结果。
SecondaryNameNode 执行 CheckPoint 操作,首先会让 NameNode 滚动 Edits并生成一个空的 edits.inprogress,滚动 Edits 的目的是给 Edits 打个标记,以后所有新的操作都写入 edits.inprogress,其他未合并的 EditsFsimage 会拷贝到 SecondaryNameNode 的本地,然后将拷贝的 EditsFsimage 加载到内存中进行合并,生成 fsimage.chkpoint, 然后将 fsimage.chkpoint 拷贝给 NameNode,重命名为 Fsimage 后替换掉原来的 Fsimage。 NameNode 在启动时就只需要加载之前未合并的 EditsFsimage 即可,因为合并过的Edits 中的元数据信息已经被记录在 Fsimage 中。
通常情况下,SecondaryNameNode每个一小时执行一次,这是由hdfs-default.xmldfs.namenode.checkpoint.period的值决定的。

NameNode故障处理

两种方法均是将SecondaryNameNode中的数据拷贝到NameNode中。

方法一

  1. 杀死NameNode进程,删除NameNode中持久化的EditsFsImages
  2. 将SecondaryNameNode中的数据复制到NameNode存储数据目录下。
  3. 启动NameNode。

方法二

使用-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode中数据拷贝到NameNode目录中。

  1. 杀死NameNode进程,删除NameNode中持久化的EditsFsImages
  2. 将SecondaryNameNode中的数据复制到NameNode存储数据目录下。
  3. 倒入检查点数据。
  4. 启动NameNode。

集群安全模式

NameNode启动

  1. NameNode启动时,首先将镜像文件(FsImage)载入内存,并执行编辑日志(Edits)中的各项操作。
  2. 在内存中成功建立文件系统元数据的映像后,立即创建一个新FsImage文件和一个空的Edits
  3. NameNode开始监听DataNode请求。这个过程期间,NameNode一直运行在安全模式,即NameNode的文件系统对于客户端来说是只读的。

DataNode启动

系统中的数据块的位置并不是由NameNode维护的,而是以块列表的形式存储在DataNode中。在系统的正常操作期间,NameNode会在内存中保留所有块位置的映射信息。
在安全模式下,各个DataNode会向 NameNode发送最新的块列表信息,NameNode了解到足够多的块位置信息之后,即可高效运行文件系统。

安全模式退出条件

如果满足“最小副本条件”,NameNode会在30秒钟之后就退出安全模式。

最小副本条件:在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1)。

在启动一个刚刚格式化的HDFS集群时,因为系统中还没有任何块(也就是不会存在副本),所以NameNode不会进入安全模式。

DataNode

DataNode工作机制

7datanode工作机制

  1. 一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和、以及时间戳。
  2. DataNode 启动后向 NameNode 注册,通过后,周期性(1 小时)的向 NameNode 上报所有的块信息。
  3. 心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数据到另一台机器,或删除某个数据块。如果超过 10 分钟没有收到某个 DataNode 的心跳,则认为该节点不可用。
  4. 集群运行中可以安全加入和退出一些机器

数据完整性的策略

DataNode使用crc校验。

  1. 当 DataNode 读取 Block 的时候,它会计算 CheckSum。
  2. 如果计算后的 CheckSum,与 Block 创建时值不一样,说明 Block 已经损坏。
  3. Client 读取其他 DataNode 上的 Block。
  4. DataNode 在其文件创建后周期验证 CheckSum。

DataNode维护

当公司业务增长,数据量越来越大时,可以很容易的对DataNode进行添加新节点、退役旧节点。

参考:

  1. 尚硅谷阳哥Hadoop:https://www.bilibili.com/video/BV1Qp4y1n7EN
  2. 东软教育科技集团张玉清老师授课内容。

大数据相关博客的目录