Hadoop(hdfs, yarn, mapreduce)理论详解_大宁哥的博客-CSDN博客

HDFS读写流程(史上最精炼详细)_bw_233的博客-CSDN博客_hdfs 读取

HDFS读写数据流程 - CoderZZZ - 博客园 (cnblogs.com)

深入浅出 Hadoop YARN - 知乎 (zhihu.com)

hadoop之mapreduce详解(基础篇) - 一寸HUI - 博客园 (cnblogs.com)

Hadoop生态之Mapreduce_小滴杂货铺的博客-CSDN博客

Hadoop中的MapReduce是什么?体系结构|例 (guru99.com)

MapReduce shuffle过程详解!_<一蓑烟雨任平生>的博客-CSDN博客_mapreduce shuffle过程详解

MapReduce shuffle过程详解_xidianycy的博客-CSDN博客_mapreduce shuffle

Hadoop简介

  • Hadoop 生态圈:(或者泛生态圈)是一个能够对大量数据进行分布式处理的软件框架,是大数据平台的开发工具,但不是一个单一的工具,也不是一种单一的技术,而是一系列技术和工具的合集。用户在不需要了解分布式底层细节的情况下,能够开发分布式程序。

  • Hadoop是基于Java语言开发的,具有很好的跨平台特性,并且可以部署在廉价的计算机集群中。

  • Hadoop大数据平台,采用分布式架构,包含多个与大数据处理相关的组件:HDFS、MapReduce、Yarn、Hbase、Hive、Spark、Kafak、Storm、HDF、Ambari等,并根据用户的实际需求完成功能定制。

  • Hadoop框架中其中最核心的组件有三个:HDFS、MapReduce和Yarn。

    • HDFS为海量数据提供了存储
    • MapReduce则为海量的数据提供了计算
    • Yarn为海量数据的处理提供了良好的系统调度。

以下是Hadoop生态中的成员:

图片1.png

img

一、HDFS——分布式文件系统

1、简介总结

总结

  • HDFS(分布式文件系统,Hadoop Distributed File System)是Hadoop的核心组件之一,是分布式计算中数据存储管理的基础,被设计成适合运行在通用硬件上的分布式文件系统。

  • 设计思想:(分而治之)将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析。

  • 大数据系统中作用:为各类分布式运算框架(如:mapreduce,spark,tez,……)提供数据存储服务。

  • HDFS架构中有两类节点:

    1)NameNode元数据节点。

    2)DataNode数据节点, 其分别执行Master和Worker任务。

  • HDFS也可以理解为一个Master+Slave体系,“一次写入,多次读取”。

HDFS的优缺点:

优点:
  • 高容错。因为其保存多个副本,通过增加副本的形式提高容错性,某个副本丢失之后,他可以通过其他副本自动恢复。通过多副本机制提高可靠性,提供容错和恢复机制。

  • 适合存储大批量数据。处理达到GB,TB,甚至PB级别的数据,处理百万规模以上的文件,处理10K节点的规模。

  • 流式文件访问,而不是随机读写

  • 一次写入多次读取,文件一旦写入不能修改,只能追加,保证数据的一致性。

    • write-once-read-many一次写入多次读取的模式(无数据一致性问题)
  • 可以构建在普通的机器上,硬件要求不高。对机器要求不高,硬盘大一点就行。

  • 存储处理非结构化数据

  • 注重数据处理的吞吐量(延迟不敏感)??

缺点:
  • 不适合低延迟数据访问。做不到毫秒级别的存储,但是适合高吞吐率场景(某一时间写入大量的数据)。
  • 不适合小文件存储。存储大量小文件会占用NameNode大量的内存来存储文件,目录、和块信息。
  • 不适合并发写入。一个文件只能有一个写入者,不允许多个线程同时写入。
  • 不适合文件随机写入修改。仅仅支持追加写入,不支持文件随机修改

hdfs不适合场景

  1. 存储海量小文件
  2. 文件被修改
  3. 大量随机读取,对于大数据的文件读取,更倾向于顺序读。因为随机读取需要寻址,浪费时间影响效率,而且顺序读取的效率会比内存读取要高

为什么HDFS更倾向于存储大文件?----结合分块存储思想

NameNode内存有限,如果内存存放大量小文件,会占用大量内存和I/O资源,使得集群反应速度慢。所以,Hadoop不适合存储大量的小文件。hdfs1.0的块大小是64M,hdfs2.0是128M。
总结:

  1. 对于集群硬盘资源造成严重浪费;
  2. NameNode本身内存有限,造成NameNode内存溢出;

img

假设有一个块,大小64m,但是存储的文件大小是10m,就浪费了54m的空间,对集群的硬盘资源造成了严重浪费。

2、HDFS架构

preview

HDFS采用了主从式(Master/Slave)的体系结构,分NameNode、SecondaryNameNode、DataNode这几个角色。

  • NameNode:是Master节点,是大领导。管理数据块映射;处理客户端的读写请求;配置副本策略;管理HDFS的名称空间
  • SecondaryNameNode:是一个小弟,分担大哥NameNode的工作量;是NameNode的冷备份;合并fsimage和fsedits然后再发给NameNode。
  • DataNode:是Slave节点,工作者,干活的。负责存储client发来的数据块block;执行数据块的读写操作

img

NameNode(NN):
  1. 管理着文件系统命名空间,负责文件和目录的创建、删除、重命名 等。
  2. 管理文件、block、 datanode之间的映射关系【文件与数据块的映射;数据块与数据节点的映射】。(所以客户端只能访问主节点才能找到数据块的位置,进而才能读取所需数据)
  • 运行 NameNode会占用大量内存和I/O资源 ------> Hadoop更倾向存储大文件原因

NameNode的最主要的作用:-----元数据管理

先来看看hdfs架构中的NameNode。NameNode是一个进程在某一个节点(机器)上,本身维护一块内存区域。内存中存储两份最重要的数据(元数据通过datanode通过心跳机制保证,datanode有新增数据,通过心跳机制告诉NameNode):

  1. 文件名->block数据块的映射关系(mapping关系)
  2. block数据块到DataNode节点之间的映射关系
DataNode(DN):
  1. 负责数据的存储和读取

    ​ 存储时:主节点分配存储位置,然后由客户端直接把数据写入相应的从节点。

    ​ 读取时:客户端从主节点获取从节点和文件的映射关系,然后到相应的位置访问文件块。

  2. 从节点也可以根据主节点的命令 创建、删除数据块和冗余复制

  3. 心跳机制,定期报告文件块列表信息

3、数据存储原理:

  1. 分块存储(Block):HDFS中文件也是分块存储,他的默认大小是128M(等于Hadoop-1.* 的版本 64M;大于等于Hadoop2.*的版本 128M), 如果一个文件小于一个块的大小,它会占用整个块的大小。
  2. **数据冗余存储:**为了实现数据的完整性,也就是整个集群中的节点可能会故障,为了保证完整性,我们通常会采用多副本存储,也就是将同一份数据的副本存储在不同的Rack上Rack理解为机架,既主机之间是否在同一个路由下)—机架感知策略

block、packet、chunk

  • 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)

例如,在client端向DataNode传数据的时候,HDFSOutputStream会有一个chunk buff,写满一个chunk后,会计算校验和并写入当前的chunk。之后再把带有校验和的chunk写入packet,当一个packet写满后,packet会进入dataQueue队列,其他的DataNode就是从这个dataQueue获取client端上传的数据并存储的。同时一个DataNode成功存储一个packet后之后会返回一个ack packet,放入ack Queue中。

分布式文件系统HDFS块大小处理及小文件问题:

Hdfs中的文件在物理上的分块存储(Block),块的大小可以通过参数[df.blocksize]配置.
hadoop2.+,3.+默认是128M, hadoop1.+ 默认是64M

hdfs设置块的大小为128M,为什么要设置这么大?
  • 目的:为了减小寻址开销和定位开销

  • 详细说明:例如客户端要访问某个文件时,第一步先从主节点获得组成这个文件的数据块的位置列表。第二步,根据位置列表获得实际存储各个数据块的从节点位置。第三步,从节点根据数据块信息在本地文件系统中找到对应文件,并且把数据返回给客户端。

在这里插入图片描述

  • 最佳传输损耗理论

    在一次传输中,寻址时间占用总传输时间的1%时,本次传输的损耗最小,为最佳性价比传输!目前硬件的发展条件,普通磁盘写的速率大概为100M/S, 寻址时间一般为10ms!

  • 近一步解释:

    ​ 1)寻址时间:找到目标block的花费时间。不论对磁盘的文件进行读还是写,都需要先进行寻址!

    ​ 2)科学的角度 寻址时间是传输时间的1%,(传输时间:数据从硬盘读取完的时间)

    ​ 3)磁盘的传输速率约100M/s

  • 所以得出:

    block的大小是100M, 块在传输时,每64K还需要校验一次,因此块大小,必须为2的n次方,最接近100M的就是128M!。 默认为128M的原因,基于最佳传输损耗理论!

  • 延伸:hdfs的块大小设置 主要取决于磁盘的传输速率

    如果公司使用的是固态硬盘,写的速度是300M/S,将块大小调整到 256M

    如果公司使用的是固态硬盘,写的速度是500M/S,将块大小调整到 512M

总体上来说,块的大小不应太大或者太小:

  • ​ 当块比较小时,增加了数据的寻址开销
  • ​ 块也不宜太大,因为通常MapReduce中的Map任务一次只处理一个块中的数据,如果启动的任务太少,就会降低并行处理的速度
HDFS分块目的:

减少后续MapReduce程序执行时等待文件的读取时间。【HDFS支持大文件存储,如果文件过大10G不分块在读取时处理数据时就会大量的将时间耗费在读取文件中,分块可以配合MapReduce程序的切片操作,减少程序的等待时间;】

HDFS采用抽象块的好处如下:

​ 1、支持大规模文件存储
​ 2、简化系统设计;
​ 3、适合数据备份。

本质:通过block数据块找到数据真正存储的本地地址。

preview

整个1、2、3数据块合起来就是文件的内容。

在存储数据时,首先要找NameNode分配DataNode来写入数据。hdfs默认会存储三份数据副本。

HDFS小文件问题处理:

HDFS中文件上传会经常有小文件的问题,每个块大小会有150字节的大小元数据存储namenode中,如果过多的小文件每个小文件都没有到达设定的块大小,都会有对应的150字节的元数据,这对namenode资源浪费很严重,同时对数据处理也会增加读取时间。

而 HDFS 中的每一个文件、目录以及文件块,在 NameNode 内存都会有记录,每一条信息大约占用150字节的内存空间。由此可见,HDFS 上存在大量的小文件(这里说的小文件是指文件大小要比一个 HDFS 块大小(在 Hadoop1.x 的时候默认块大小64M,可以通过dfs.blocksize 来设置;但是到了 Hadoop 2.x 的时候默认块大小为128MB了,可以通过 dfs.block.size 设置) 小得多的文件。)至少会产生以下几个负面影响:

  • 大量小文件的存在势必占用大量的 NameNode 内存,从而影响 HDFS 的横向扩展能力。

  • 另一方面,如果我们使用 MapReduce 任务来处理这些小文件,**因为每个 Map 会处理一个 HDFS 块;这会导致程序启动大量的 Map 来处理这些小文件,( 读取小文件数据的任务执行时,消耗过多的集群资源。**因为map task在执行的时候一般只处理1个文件,如果这个时候要读取的文件过多,就会造成大量的map task启动。) 虽然这些小文件总的大小并非很大,却占用了集群的大量资源!

HDFS自带的小文件存储解决方案:

对于小文件问题,Hadoop自身提供了三种解决方案:

  1. Hadoop Archive(HRA—文件归档):采用har归档方式,将小文件归档

    文件归档在这里的意思是将文件再次进行整理和保存,使之更易管理和保存。而Hadoop中的归档是在HDFS之上又构建了一个新的抽象层,叫HAR(Hadoop Archives ),访问的格式变为了har:// URL。它的实现原理如下图。

    img

  2. Sequence File:

    sequence file由一系列的二进制的对组成,其中key为小文件的名字,value的file content。通过改变文件的写出方式,写入到SequenceFile格式的文件中。这主要是因为SequenceFile独有的存储格式决定了它可以很好的满足小文件存储的需求。SequenceFile文件内部存储数据的方式是以下面key-value的形式拼接而成。
    img

  3. CombineFileInputFormat

    CombineInputFormat的功能,是将一个目录(可能包括多个小文件,不包括子目录)作为一个map的输入,而不是通常使用一个文件作为输入。

数据冗余存储

为了保证系统的容错性和可用性。hdfs采用多副本存储方式对数据进行冗余存储,通常一个数据块的多个副本会被分到不同的从节点上。

优点如下:

1、加快数据传输速度;
2、容易检查数据错误;
3、保证数据的可靠性。

  • 冗余存储中,例如有三个副本,那么一个保存在本地,一个保存在同一机架的DataNode,还有一个保存在不同机架的DataNode.

元数据管理—FsImage、EditLog:

NN负责管理HDFS中所有的元数据,包括但不限于文件/目录结构、文件权限、块ID/大小/数量、副本策略等等。客户端执行读写操作前,先从NN获得元数据。当NN在运行时,元数据都是保存在内存中,以保证响应时间

显然,元数据只保留在内存中是非常不可靠的,所以也需要持久化到磁盘。NN内部有两类文件用于持久化元数据

  • fsimage文件,以fsimage_为前缀,是序列化存储的元数据的整体快照;用于维护文件系统树以及文件树种所有的文件和文件夹的元数据
  • edit log文件,以edits_为前缀,是顺序存储的元数据的增量修改(即客户端写入事务)日志。操作日志记录文件。记录了所有针对文件的创建、删除、重命名等操作记录。

这两类文件均存储在${dfs.namenode.name.dir}/current/路径下,查看其中的内容:

可见,fsimage和edit log文件都会按照事务ID来分段。当前正在写入的edit log文件名会带有"inprogress"标识,而seen_txid文件保存的就是当前正在写入的edit log文件的起始事务ID。

  • 在任意时刻,最近的fsimage和edit log文件的内容加起来就是全量元数据。NN在启动时,就会将最近的fsimage文件加载到内存,并重放它之后记录的edit log文件,恢复元数据的现场。

完整的元数据信息信息就应该由 FSImage 文件和 edit log 文件组成。

  • fsimage 中存储的信息就相当于整个 hdfs 在某一时刻的一个快照。
  • 在某一次启动HDFS时,会从 FSImage 文件中读取当前 HDFS 文件的 metadata ,之后对 HDFS 的所有操作都会记录到 edit log 文件中

img

在这里插入图片描述

  • NameNode主节点记录了每个文件中各个块在的从节点的位置信息,但是并不持久化存储这些信息,而是在系统每次启动时扫描所有数据节点重构得到这些信息。【可以类比区块链信息追溯】

  • NameNode每次重启之后,先把FsImage的内容加载到内存中,然后根据EditLog中操作记录来复盘最新的元数据状态。这个操作完成之后,会把最新状态重新写到FsImage,并且清空EditLog

    主节点启动成功并进入正常运行以后,HDFS的更新操作都会被写入到EditLog,这是因为对于分布式文件系统而言,FsImage文件通常都很庞大,如果所有的更新操作都直接往Fsimage文件中添加的话,那么系统会变得非常缓慢。【理解为merge】

  • 从节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者主节点的调度来进行数据的存储和检索,并且向主节点定期发送自己所存储的块的列表。每个从节点的数据会被保存在各自节点的本地文件系统中。

CheckPoint与SecondaryNameNode:

  • 在主节点运行期间,HDFS会不断发生更新操作,这些更新操作都是直接被写入到Editlog文件,因此Editlog文件也会逐渐变大。在主节点运行期间,不断变大的Editlog不会对系统性能产生影响。
  • 但是,当主节点重启时,需要将FsImage加载到内存中,再逐条执行Editlog中的操作记录,使得FsImage保持最新状态。如果FsImage很大,就会导致整个过程非常缓慢,使得主节点在启动过程中长期处于**“安全模式”**,无法对外提供写操作,影响用户使用。

CheckPoint:

为了避免edit log文件过大,以及缩短NN启动时恢复元数据的时间,我们需要定期地将edit log文件合并到fsimage文件,该合并过程叫做checkpoint

SencondaryNameNode(SNN):

由于NN的负担已经比较重,再让它来进行I/O密集型的文件合并操作就不太科学了,所以Hadoop引入了SNN负责这件事。也就是说,SNN是辅助NN进行checkpoint操作的角色

第二主节点SNN:

  • 首先,它可以完成Editlog和FsImage的合并操作,减小Editlog文件大小,缩短主节点的重启时间。
  • 其次,它可以作为主节点的检查点,保存主节点中的元数据信息。

checkpoint的触发由hdfs-site.xml中的两个参数来控制。

dfs.namenode.checkpoint.period:触发checkpoint的周期长度,默认为1小时。
dfs.namenode.checkpoint.txns:两次checkpoint之间最大允许进行的事务数(即edit log的增量条数),默认为100万。
只要满足上述两个参数的条件之一,就会触发checkpoint过程,叙述如下:

  1. NN生成新的edits_inprogress文件,后续的事务日志将写入该文件中,之前正在写的edit log文件即为待合并状态
  2. 将待合并的edit log文件和fsimage文件一起复制到SNN本地。
  3. SNN像NN启动时一样,将fsimage文件加载到内存,并重放edit log文件进行合并。生成合并结果为fsimage.chkpoint文件。
  4. SNN将fsimage.chkpoint复制回NN,并重命名为正式的fsimage文件名。

img

另外,为了避免fsimage文件占用太多磁盘空间,通过dfs.namenode.num.checkpoints.retained参数可以指定保留多少个fsimage文件,默认值为2。

HA模式下 Checkpoint 过程

上面说的都是集群只有一个NN的情况。如果有多个NN并且开启了HA的话,SNN就没用了。

在HA模式下 checkpoint 过程由StandBy NameNode来进行:

  1. Active NameNode将edit log文件会同时写入多个 JournalNodes 节点的 dfs.journalnode.edits.dir 路径下,(JournalNodes 的个数为大于1的奇数,当有不超过一半的 JournalNodes 出现故障时,仍然能保证集群的稳定运行)。---------Active NN会将edit log文件同时写到JournalNode集群
  2. StandBy NameNode 会读取 FSImage 文件中的内容,并且每隔一段时间就会把 Active NameNode 写入edit log中的记录读取出来,这样 StandBy NameNode 的NameNode进程中一直保持着 hdfs 文件系统的最新状况的 namespace。当达到 checkpoint 条件的某一个时,就会直接将该信息写入一个新的 FSImage 文件中,然后通过HTTP传输给 Active NameNode 。----------Standby NN从JournalNode集群拉取edit log文件进行合并,并保持fsimage文件与Active NN的同步

img

img

如上图所示,整个同步过程如下:

  1. StandBy NameNode 检查是否达到 checkpoint 条件:离上一次checkpoint操作是否已经有一个小时,或者HDFS已经进行了100万次操作。
  2. StandBy NameNode 检查达到 checkpoint 条件后,将该 namespace 以fsimage.ckpt_txid 格式保存到 StandBy NameNode 的磁盘上,并且随之生成一个MD5文件。然后将该fsimage.ckpt_txid文件重命名为fsimage_txid。
  3. 然后 StandBy NameNode 通过HTTP联系 Active NameNode。
  4. Active NameNode 通过HTTP从 StandBy NameNode 获取最新的fsimage_txid文件并保存为fsimage.ckpt_txid,然后也生成一个MD5,将这个MD5与SBNN的MD5文件进行比较,确认ANN已经正确获取到了SBNN最新的fsimage文件。然后将fsimage.ckpt_txid文件重命名为fsimage_txit。
  5. 通过上面一系列的操作,StandBy NameNode 上最新的 FSImage 文件就成功同步到了 Active NameNode 上。

JournalNode 其实不参与 NameNode 的 metadata 同步之类的操作,它只是个忠实的存储,存储来自于NameNode 的操作日志,Active NameNode 在文件系统被修改时,会向JournalNode写入修改记录,而 Standby NameNode 可以方便的读取到这样的修改记录。

数据存取策略

存取策略总结:

  1. 数据存放,一部分备份放在相同Rack(机架),一部分放在不同Rack, 目的是物理容灾
  2. 数据读取,当客户端发起读取数据时候,主节点优先找与客户端同Rack的从节点进行读取,如果没有才考虑跨机架的从节点。
  3. 数据复制:采用了流水线复制的策略
数据存放
  • 为了提高数据的可靠性和系统的可用性,以及充分利用网络带宽,HDFS采用以RACK(机架)为基础的数据存放策略。一个HDFS集群通常包含多个RACK,不同RACK之间的数据通信需要经过交换机或路由器,同一RACK则不需要。

  • HDFS默认的冗余复制因子是3,每一个文件块会同时保存到3个地方,其中,有两份副本放在同一RACK的不同机器上,第三个副本放在不同RACK的机器上面,这样即可以保证RACK出口发生异常时的数据恢复,也可以提高数据读写能力。

数据读取
  • HDFS提供了一个API可以确定一个主节点所属Rack的ID,客户端通过调用API获取自己所属的Rack ID。
  • 当客户端读取数据时,从主节点获取数据块不同副本的存放位置列表,列表中包含了副本所在的从节点,可以调用API来确定客户端和这些从节点所属的Rack ID。当发现某个数据块副本的Rack ID和客户端对应的Rack ID相同时,就优先选择该副本读取数据。
数据复制
  • HDFS的数据复制采用了流水线复制的策略,这样大大提高了数据复制过程的效率。当客户端要往HDFS中写入一个文件时,这个文件首先被写入本地,并被切分成若干块,每个块的大小由HDFS设定的值来确定。每个块就向HDFS集群中的主节点发送写请求,主节点就返回一个可写入的从节点的列表,再写入。

4、数据读写过程

(1)读取文件过程

在这里插入图片描述

img

整体过程:

1、客户端通过调用FileSystem对象的open()来读取希望打开的文件。对于HDFS来说,这个对象是分布式文件系统的一个实例。

​ 2、DistributedFileSystem通过RPC来调用namenode,以确定文件的开头部分的块位置。对于每一块,namenode返回具有该块副本的datanode地址。此外,这些datanode根据他们与client的距离来排序(根据网络集群拓扑上的就近原则),挑选一台DataNode(网络拓扑上的就近原则,如果都一样,则随机挑选一台DataNode)服务器,请求建立socket流

3、DataNode开始发送数据(从磁盘里面读取数据放入流,以packet(一个packet为64kb)为单位来做校验)

4、客户端以packet为单位接收,先在本地缓存,然后写入目标文件

​ 5、到达块的末端时,DFSInputStream会关闭与datanode间的联系,然后为下一个块找到最佳的datanode。client端只需要读取一个连续的流,这些对于client来说都是透明的。

(2)写入文件过程

HDFS读流程

img

整体过程:

1、客户端向NameNode发出写文件请求。NameNode检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。

(注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)

2、NameNode返回是否可以上传

3、Client先对文件进行切分(按128MB的块切分文件)

​ 4、请求第一个block该传输到哪些DataNode服务器上,client将NameNode返回的分配的可写的DataNode列表

​ 5、client将要上传的数据和NameNode返回的分配的可写的DataNode列表一同发送给最近的第一个DataNode节点(本质上是一个RPC调用,建立pipeline),DataNode 1收到请求会继续调用DataNode 2,然后DataNode 2调用DataNode 3,client端和NameNode分配的多个DataNode构成pipeline管道,然后逐级返回客户端。

​ 6、Client开始往DataNode 1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以pocket为单位传输数据。写入的时候DataNode会进行数据校验,它并不是通过一个packet进行一次校验而是以chunk为单位进行校验(512byte)。DataNode 1收到一个packet就会传给DataNode 2,DataNode 2传给DataNode 3…
(注:并不是写好一个块或一整个文件后才向后分发)------------流水线复制策略

7、当一个block传输完成之后,Client再次请求NameNode上传第二个block的服务器.

​ 8、每个DataNode写完一个块后,会返回确认信息。
(注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生)

(一个内部的数据包队列来等待datanode收到确认,称为确认队列。一个包只有在被管线中所有的节点确认后才会被移除出确认队列。如果在有数据写入期间,datanode发生故障, 则会执行下面的操作,当然这对写入数据的client而言是透明的。首先管线被关闭,确认队列中的任何包都会被添加回数据队列的前面,以确保故障节点下游的datanode不会漏掉任意一个包。为存储另一正常datanode的当前数据块制定一个新的标识,并将该标识传给namenode,以便故障节点datanode在恢复后可以删除存储的部分数据块。从管线中删除故障数据节点并且把余下的数据块写入管线中的两个正常的datanode。namenode注意到块复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接收处理。只要dfs.replication.min的副本(默认是1)被写入,写操作就是成功的,并且这个块会在集群中被异步复制,直到其满足目标副本数(dfs.replication 默认值为3)。

​ 9、写完数据,关闭输输出流。

​ 10、发送完成信号给NameNode。
(注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报最终一致性其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性,需在返回成功前等待块进行最小量的复制。)

读写过程,数据完整性如何保持?

通过校验和。因为每个chunk中都有一个校验位,一个个chunk构成packet,一个个packet最终形成block,故可在block上求校验和。

HDFS 的client端即实现了对 HDFS 文件内容的校验和 (checksum) 检查。当客户端创建一个新的HDFS文件时候,分块后会计算这个文件每个数据块的校验和此校验和会以一个隐藏文件形式保存在同一个 HDFS 命名空间下。当client端从HDFS中读取文件内容后,它会检查分块时候计算出的校验和(隐藏文件里)和读取到的文件块中校验和是否匹配,如果不匹配,客户端可以选择从其他 Datanode 获取该数据块的副本。

HDFS中文件块目录结构具体格式如下:

${dfs.datanode.data.dir}/
├── current
│ ├── BP-526805057-127.0.0.1-1411980876842
│ │ └── current
│ │ ├── VERSION
│ │ ├── finalized
│ │ │ ├── blk_1073741825
│ │ │ ├── blk_1073741825_1001.meta
│ │ │ ├── blk_1073741826
│ │ │ └── blk_1073741826_1002.meta
│ │ └── rbw
│ └── VERSION
└── in_use.lock

in_use.lock表示DataNode正在对文件夹进行操作
rbw是“replica being written”的意思,该目录用于存储用户当前正在写入的数据。
Block元数据文件(*.meta)由一个包含版本、类型信息的头文件和一系列校验值组成。校验和也正是存在其中。

5、数据错误和恢复

主节点出错的恢复-----SecondaryNameNode

1、将主节点上的元数据信息同步存储到其他文件系统中;

2、运行一个第二主节点,当主节点宕机以后,可以利用第二从节点来弥补,进行数据恢复。

从节点出错的恢复

每个从节点都会定期向主节点发送信息,报告自己的状态。当从节点故障时,就会被标记为宕机,这个时候主节点就不会再给它们发送IO请求。这个时候,如果发现某些数据块数量少于冗余因子,就会启动数据冗余复制,为它生成新的副本。

数据出错的恢复

客户端在读取数据后,会采用md5和sha1对数据进行校验,以确保读取到正确的数据。如果发现错误,就会读取该数据块的副本。

SHA1和MD5

**SHA1和MD5都是哈希算法,**其中MD5在速度方面是最高效的。
但是,与MD5相比SHA1是最安全的算法
两种哈希算法的基础是它们从接收到的消息中生成加密摘要或哈希的能力。

这两个功能的一些基本要素包括:

  • 因为数据集是唯一的,所以永远不会有两个类似的哈希或摘要。
  • 正在传送的消息的大小不会影响生成的摘要或哈希的长度。
  • 一旦执行,这些功能将无法撤消或撤消。

哈希算法主要用于验证文件,而不是对发送的消息进行加密。

MD5SHA1
MD5是Message Digest的首字母缩写另一方面,SHA1指的是安全哈希算法。
与SHA1相比,MD5在速度上仍然更快且更可靠。同样,与MD5相比,SHA1的速度相对较慢。
消息摘要的长度为168位在SHA1中,消息散列的最大长度为160位。
与SHA1相比,MD5很简单SHA1比MD5更复杂
攻击者将需要2 ^ 128次操作才能使用MD5算法程序生成第一条消息。在SHA1中,侵略者将需要2 ^ 160次操作,因此要找出它非常具有挑战性。
在MD5中,攻击者需要执行2 ^ 64次操作才能找出是否有两个消息共享相同的消息摘要。相反,攻击者在SHA1中需要进行2 ^ 80次操作,才能找出具有相同哈希或摘要的两条消息。
MD5提供较差或较弱的安全SHA1提供可容忍或平衡的安全性。

6、HDFS - 可靠性

HDFS 的可靠性主要有以下几点:

  • 冗余副本策略
  • 机架策略
  • 心跳机制
  • 安全模式
  • 效验和
  • 回收站
  • 元数据保护
  • 快照机制

1).冗余副本策略

可以在 hdfs-site.xml 中设置复制因子指定副本数量

所有数据块都可副本

DataNode 启动时,遍历本地文件系统,产生一份 HDFS 数据块和本地文件的对应关系列表 (blockreport) 汇报给 Namenode

2).机架策略

HDFS 的"机架感知",通过节点之间发送一个数据包,来感应它们是否在同一个机架

一般在本机架放一个副本,在其他机架再存放一个副本,这样可以防止机架失效时丢失数据,也可以提高带宽利用率

3).心跳机制

NameNode 周期性从 DataNode 接受心跳信息和块报告

NameNode 根据块报告验证元数据

没有按时发送心跳的 DataNode 会被标记为宕机,不会再给他任何 I/O 请求

如果 DataNode 失效造成副本数量下降,并且低于预先设定的值,NameNode 会检测出这些数据库,并在合适的时机重新复制

引发重新复制的原因还包括数据副本本身损坏,磁盘错误,复制因子被增大等

4).安全模式

NameNode 启动时会先经过一个 “安全模式” 阶段

安全模式阶段不会产生数据写

在此阶段 NameNode 收集各个 DataNode 的报告, 当数据块达到最小副本数以上时,会被认为是"安全"的

在一定比例(可设置) 的数据块被确定为"安全" 后 ,在过若干时间,安全模式结束

当检测到副本数不足的数据块时,该块会被复制,直到达到最小副本数

5).效验和

在文件创立时,每个数据块都产生效验和

效验和会作为单独一个隐藏文件保存在命名空间下

客户端获取数据时可以检查效验和是否相同,从而发现数据块是否损坏

如果正在读取的数据块损坏,则可以继续读取其他副本

6).回收站

删除文件时,其实是放入回收站 /trash

回收站里的文件是可以快速恢复的

可以设置一个时间值,当回收站里文件的存放时间超过了这个值,就被彻底删除,并且释放占用的数据块

7).元数据保护

映像文件和事物日志是 NameNode 的核心数据.可以配置为拥有多个副本

副本会降低 NameNode 的处理速度,但增加安全

NameNode 依然是单点,如果发生故障要手工切换

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐