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是基于Java语言开发的,具有很好的跨平台特性,并且可以部署在廉价的计算机集群中。
Hadoop大数据平台,采用分布式架构,包含多个与大数据处理相关的组件:HDFS、MapReduce、Yarn、Hbase、Hive、Spark、Kafak、Storm、HDF、Ambari等,并根据用户的实际需求完成功能定制。
Hadoop框架中其中最核心的组件有三个:HDFS、MapReduce和Yarn。
以下是Hadoop生态中的成员:
HDFS(分布式文件系统,Hadoop Distributed File System)是Hadoop的核心组件之一,是分布式计算中数据存储管理的基础,被设计成适合运行在通用硬件上的分布式文件系统。
设计思想:(分而治之)将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析。
在大数据系统中作用:为各类分布式运算框架(如:mapreduce,spark,tez,……)提供数据存储服务。
HDFS架构中有两类节点:
1)NameNode元数据节点。
2)DataNode数据节点, 其分别执行Master和Worker任务。
HDFS也可以理解为一个Master+Slave体系,“一次写入,多次读取”。
高容错。因为其保存多个副本,通过增加副本的形式提高容错性,某个副本丢失之后,他可以通过其他副本自动恢复。通过多副本机制提高可靠性,提供容错和恢复机制。
适合存储大批量数据。处理达到GB,TB,甚至PB级别的数据,处理百万规模以上的文件,处理10K节点的规模。
流式文件访问,而不是随机读写
一次写入多次读取,文件一旦写入不能修改,只能追加,保证数据的一致性。
可以构建在普通的机器上,硬件要求不高。对机器要求不高,硬盘大一点就行。
存储处理非结构化数据
注重数据处理的吞吐量(延迟不敏感)??
hdfs不适合场景
- 存储海量小文件
- 文件被修改
- 大量随机读取,对于大数据的文件读取,更倾向于顺序读。因为随机读取需要寻址,浪费时间影响效率,而且顺序读取的效率会比内存读取要高
为什么HDFS更倾向于存储大文件?----结合分块存储思想
NameNode内存有限,如果内存存放大量小文件,会占用大量内存和I/O资源,使得集群反应速度慢。所以,Hadoop不适合存储大量的小文件。hdfs1.0的块大小是64M,hdfs2.0是128M。
总结:
- 对于集群硬盘资源造成严重浪费;
- NameNode本身内存有限,造成NameNode内存溢出;
假设有一个块,大小64m,但是存储的文件大小是10m,就浪费了54m的空间,对集群的硬盘资源造成了严重浪费。
HDFS采用了主从式(Master/Slave)的体系结构,分NameNode、SecondaryNameNode、DataNode这几个角色。
NameNode的最主要的作用:-----元数据管理
先来看看hdfs架构中的NameNode。NameNode是一个进程在某一个节点(机器)上,本身维护一块内存区域。内存中存储两份最重要的数据(元数据通过datanode通过心跳机制保证,datanode有新增数据,通过心跳机制告诉NameNode):
负责数据的存储和读取。
存储时:主节点分配存储位置,然后由客户端直接把数据写入相应的从节点。
读取时:客户端从主节点获取从节点和文件的映射关系,然后到相应的位置访问文件块。
从节点也可以根据主节点的命令 创建、删除数据块和冗余复制
心跳机制,定期报告文件块列表信息
Rack理解为机架,既主机之间是否在同一个路由下
)—机架感知策略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中的文件在物理上的分块存储(Block),块的大小可以通过参数[df.blocksize]配置.
hadoop2.+,3.+默认是128M, hadoop1.+ 默认是64M
目的:为了减小寻址开销和定位开销。
详细说明:例如客户端要访问某个文件时,第一步先从主节点获得组成这个文件的数据块的位置列表。第二步,根据位置列表获得实际存储各个数据块的从节点位置。第三步,从节点根据数据块信息在本地文件系统中找到对应文件,并且把数据返回给客户端。
最佳传输损耗理论:
在一次传输中,寻址时间占用总传输时间的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程序执行时等待文件的读取时间。【HDFS支持大文件存储,如果文件过大10G不分块在读取时处理数据时就会大量的将时间耗费在读取文件中,分块可以配合MapReduce程序的切片操作,减少程序的等待时间;】
HDFS采用抽象块的好处如下:
1、支持大规模文件存储;
2、简化系统设计;
3、适合数据备份。
本质:通过block数据块找到数据真正存储的本地地址。
整个1、2、3数据块合起来就是文件的内容。
在存储数据时,首先要找NameNode分配DataNode来写入数据。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启动。) 虽然这些小文件总的大小并非很大,却占用了集群的大量资源!
对于小文件问题,Hadoop自身提供了三种解决方案:
Hadoop Archive(HRA—文件归档):采用har归档方式,将小文件归档
文件归档在这里的意思是将文件再次进行整理和保存,使之更易管理和保存。而Hadoop中的归档是在HDFS之上又构建了一个新的抽象层,叫HAR(Hadoop Archives ),访问的格式变为了har:// URL。它的实现原理如下图。
Sequence File:
sequence file由一系列的二进制的对组成,其中key为小文件的名字,value的file content。通过改变文件的写出方式,写入到SequenceFile格式的文件中。这主要是因为SequenceFile独有的存储格式决定了它可以很好的满足小文件存储的需求。SequenceFile文件内部存储数据的方式是以下面key-value的形式拼接而成。
CombineFileInputFormat
CombineInputFormat的功能,是将一个目录(可能包括多个小文件,不包括子目录)作为一个map的输入,而不是通常使用一个文件作为输入。
为了保证系统的容错性和可用性。hdfs采用多副本存储方式对数据进行冗余存储,通常一个数据块的多个副本会被分到不同的从节点上。
优点如下:
1、加快数据传输速度;
2、容易检查数据错误;
3、保证数据的可靠性。
NN负责管理HDFS中所有的元数据,包括但不限于文件/目录结构、文件权限、块ID/大小/数量、副本策略等等。客户端执行读写操作前,先从NN获得元数据。当NN在运行时,元数据都是保存在内存中,以保证响应时间。
显然,元数据只保留在内存中是非常不可靠的,所以也需要持久化到磁盘。NN内部有两类文件用于持久化元数据:
这两类文件均存储在${dfs.namenode.name.dir}/current/路径下,查看其中的内容:
可见,fsimage和edit log文件都会按照事务ID来分段。当前正在写入的edit log文件名会带有"inprogress"标识,而seen_txid文件保存的就是当前正在写入的edit log文件的起始事务ID。
完整的元数据信息信息就应该由 FSImage 文件和 edit log 文件组成。
- fsimage 中存储的信息就相当于整个 hdfs 在某一时刻的一个快照。
- 在某一次启动HDFS时,会从 FSImage 文件中读取当前 HDFS 文件的 metadata ,之后对 HDFS 的所有操作都会记录到 edit log 文件中。
NameNode主节点记录了每个文件中各个块在的从节点的位置信息,但是并不持久化存储这些信息,而是在系统每次启动时扫描所有数据节点重构得到这些信息。【可以类比区块链信息追溯】
NameNode每次重启之后,先把FsImage的内容加载到内存中,然后根据EditLog中操作记录来复盘最新的元数据状态。这个操作完成之后,会把最新状态重新写到FsImage,并且清空EditLog,
主节点启动成功并进入正常运行以后,HDFS的更新操作都会被写入到EditLog,这是因为对于分布式文件系统而言,FsImage文件通常都很庞大,如果所有的更新操作都直接往Fsimage文件中添加的话,那么系统会变得非常缓慢。【理解为merge】
从节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者主节点的调度来进行数据的存储和检索,并且向主节点定期发送自己所存储的块的列表。每个从节点的数据会被保存在各自节点的本地文件系统中。
CheckPoint:
为了避免edit log文件过大,以及缩短NN启动时恢复元数据的时间,我们需要定期地将edit log文件合并到fsimage文件,该合并过程叫做checkpoint。
SencondaryNameNode(SNN):
由于NN的负担已经比较重,再让它来进行I/O密集型的文件合并操作就不太科学了,所以Hadoop引入了SNN负责这件事。也就是说,SNN是辅助NN进行checkpoint操作的角色。
第二主节点SNN:
checkpoint的触发由hdfs-site.xml中的两个参数来控制。
dfs.namenode.checkpoint.period
:触发checkpoint的周期长度,默认为1小时。
dfs.namenode.checkpoint.txns
:两次checkpoint之间最大允许进行的事务数(即edit log的增量条数),默认为100万。
只要满足上述两个参数的条件之一,就会触发checkpoint过程,叙述如下:
另外,为了避免fsimage文件占用太多磁盘空间,通过dfs.namenode.num.checkpoints.retained
参数可以指定保留多少个fsimage文件,默认值为2。
上面说的都是集群只有一个NN的情况。如果有多个NN并且开启了HA的话,SNN就没用了。
在HA模式下 checkpoint 过程由StandBy NameNode来进行:
如上图所示,整个同步过程如下:
JournalNode 其实不参与 NameNode 的 metadata 同步之类的操作,它只是个忠实的存储,存储来自于NameNode 的操作日志,Active NameNode 在文件系统被修改时,会向JournalNode写入修改记录,而 Standby NameNode 可以方便的读取到这样的修改记录。
存取策略总结:
为了提高数据的可靠性和系统的可用性,以及充分利用网络带宽,HDFS采用以RACK(机架)为基础的数据存放策略。一个HDFS集群通常包含多个RACK,不同RACK之间的数据通信需要经过交换机或路由器,同一RACK则不需要。
HDFS默认的冗余复制因子是3,每一个文件块会同时保存到3个地方,其中,有两份副本放在同一RACK的不同机器上,第三个副本放在不同RACK的机器上面,这样即可以保证RACK出口发生异常时的数据恢复,也可以提高数据读写能力。
整体过程:
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来说都是透明的。
整体过程:
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)由一个包含版本、类型信息的头文件和一系列校验值组成。校验和也正是存在其中。
1、将主节点上的元数据信息同步存储到其他文件系统中;
2、运行一个第二主节点,当主节点宕机以后,可以利用第二从节点来弥补,进行数据恢复。
每个从节点都会定期向主节点发送信息,报告自己的状态。当从节点故障时,就会被标记为宕机,这个时候主节点就不会再给它们发送IO请求。这个时候,如果发现某些数据块数量少于冗余因子,就会启动数据冗余复制,为它生成新的副本。
客户端在读取数据后,会采用md5和sha1对数据进行校验,以确保读取到正确的数据。如果发现错误,就会读取该数据块的副本。
SHA1和MD5
**SHA1和MD5都是哈希算法,**其中MD5在速度方面是最高效的。
但是,与MD5相比,SHA1是最安全的算法。
两种哈希算法的基础是它们从接收到的消息中生成加密摘要或哈希的能力。
这两个功能的一些基本要素包括:
哈希算法主要用于验证文件,而不是对发送的消息进行加密。
MD5 | SHA1 |
---|---|
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提供可容忍或平衡的安全性。 |
HDFS 的可靠性主要有以下几点:
可以在 hdfs-site.xml 中设置复制因子指定副本数量
所有数据块都可副本
DataNode 启动时,遍历本地文件系统,产生一份 HDFS 数据块和本地文件的对应关系列表 (blockreport) 汇报给 Namenode
HDFS 的"机架感知",通过节点之间发送一个数据包,来感应它们是否在同一个机架
一般在本机架放一个副本,在其他机架再存放一个副本,这样可以防止机架失效时丢失数据,也可以提高带宽利用率
NameNode 周期性从 DataNode 接受心跳信息和块报告
NameNode 根据块报告验证元数据
没有按时发送心跳的 DataNode 会被标记为宕机,不会再给他任何 I/O 请求
如果 DataNode 失效造成副本数量下降,并且低于预先设定的值,NameNode 会检测出这些数据库,并在合适的时机重新复制
引发重新复制的原因还包括数据副本本身损坏,磁盘错误,复制因子被增大等
NameNode 启动时会先经过一个 “安全模式” 阶段
安全模式阶段不会产生数据写
在此阶段 NameNode 收集各个 DataNode 的报告, 当数据块达到最小副本数以上时,会被认为是"安全"的
在一定比例(可设置) 的数据块被确定为"安全" 后 ,在过若干时间,安全模式结束
当检测到副本数不足的数据块时,该块会被复制,直到达到最小副本数
在文件创立时,每个数据块都产生效验和
效验和会作为单独一个隐藏文件保存在命名空间下
客户端获取数据时可以检查效验和是否相同,从而发现数据块是否损坏
如果正在读取的数据块损坏,则可以继续读取其他副本
删除文件时,其实是放入回收站 /trash
回收站里的文件是可以快速恢复的
可以设置一个时间值,当回收站里文件的存放时间超过了这个值,就被彻底删除,并且释放占用的数据块
映像文件和事物日志是 NameNode 的核心数据.可以配置为拥有多个副本
副本会降低 NameNode 的处理速度,但增加安全性
NameNode 依然是单点,如果发生故障要手工切换