Hadoop(hdfs, yarn, mapreduce)理论详解
理论指导实践,hadoop的原理是当前大数据技术的理论基础。对于开发者而言,容易只顾操作而忽视理论,操作可以在短期内上手,而恰恰是理论才可以指引着技术人不断前行和突破。 下面陆续跟大家详细交流关于Hadoop中Hdfs和yarn两大核心原理以及MR原理。
如下内容比较基础且重要,经过大量收集优秀博文内容 对其对比、修改和再次润色,最终呈现给大家。
1.hdfs分布式文件系统原理
hdfs简要说明
hdfs(分布式文件系统,Hadoop Distributed File System)是hadoop的核心组件之一,是分布式计算中数据存储管理的基础,被设计成适合运行在通用硬件上的分布式文件系统。
Hdfs架构中有两类节点。1)NameNode元数据节点。2)DataNode数据节点, 其分别执行Master和Worker任务。
Hdfs也可以理解为一个Master+Slave体系, ‘一次写入,多次读取。’
Hdfs的设计思想是分而治之。(数据结构的经典思想), 分而治之将大文件,大批量文件分布式存在大量单独的机器上。
hdfs的优缺点
#优点1)高容错。
因为其保存多个副本,通过增加副本的形式挺高容错性,某个副本丢失之后,他可以通过其他副本自动恢复。
通过多副本机制提高可靠性,提供容错和恢复机制。
2)适合存储大批量数据。
处理达到GB,TB,甚至PB几倍的数据,处理百万规模以上的文件梳理,处理10K节点的规模。
3)流式文件访问。
一次写入多次读取,文件一旦写入不能修改,只能追加,保证数据的一致性。
4)可以构建在普通的机器上,硬件要求不是很高。
对机器要求不高,硬盘大一点就行。
#缺点1)不适合低延迟数据访问。
做不到毫秒级别的存储,但是适合高吞吐率场景(某一时间写入大量的数据)。
2)不适合小文件存储。
存储大量小文件会占用NameNode大量的内存来存储文件,目录、和块信息。
3)不适合并发写入,随机写入。
一个文件不允许多个线程同时写入,仅仅支持数据追加,不支持文件随机修改。
hdfs架构图
三个关键结构:
1)NameNode
2)DataNode
3)SecondaryNameNode
接下来按照上面两个图给大家介绍一下。图片来源于网络,详略不当之处还望指正。
#hdfs分布式文件系统的结构
分布式文件系统在物理结构上是有计算机集群的多个节点构成(主节点和一些从节点)。
1.主节点(NameNode):
1)负责文件和目录的创建、删除、重命名 等。
2)管理从节点,和文件块的隐射关系。(所以客户端只能访问主节点才能找到数据块的位置,进而才能读取所需数据)
2.从节点(DataNode):
1)负责数据的存储和读取。
存储时:主节点分配存储位置,然后由客户端直接把数据写入相应的从节点。
读取时:客户端从主节点获取从节点和文件的映射关系,然后到相应的位置访问文件块。
2)从节点也可以根据主节点的命令 创建、删除、数据块和冗余复制
#细节:1)hdfs中文件也是分块存储,他的默认大小是64M, 如果一个文件小于一个块的大小,它会占用整个块的大小。【后面做重点解释——《2.分布式文件系统HDFS块大小处理及小文件问题》】
2)为了实现数据的完整性,也就是整个集群中的节点可能会故障,为了保证完整性,我们通常会采用多副本存储,也就是将同一份数据的副本存储在不同的Rack上(Rack理解为机架,既主机之间是否在同一个路由下)
hdfs概念1——块
#hdfs设置块的大小为64M、128M、256M为什么要设置这么大?
·目的:为了减小寻址开销和定位开销。
·详细说明:例如客户端要访问某个文件时,第一步先从主节点获得组成这个文件的数据块的位置列表。第二步,根据位置列表获得实际存储各个数据块的从节点位置。第三步,从节点根据数据块信息在本地文件系统中找到对应文件,并且把数据返回给客户端。
#所以说块的大小不应太大或者太小。
当块比较小时,增加了数据的寻址开销。
块也不宜太大,因为通常MapReduce中的Map任务一次只处理一个块中的数据,如果启动的任务太少,就会降低并行处理的速度
【下文做详细介绍】
#HDFS采用抽象块的好处如下:1、支持大规模文件存储;
2、简化系统设计;
3、适合数据备份。
hdfs概念2——FsImage、EditLog和SecondNameNode
FsImage:用于维护文件系统树以及文件树种所有的`文件`和`文件夹`的`元数据`。
EditLog:操作日志记录文件。记录了所有针对文件的`创建`、`删除`、`重命名`等操作记录。
#主节点记录了每个文件中各个块坐在的从节点的位置信息,但是并不持久化存储这些信息,而是在系统每次启动时扫描所有数据节点重构得到这些信息。【可以类比区块链信息追溯】#NameNode每次重启之后,先把FsImage的内容加载到内存中,然后根据EditLog中操作记录来复盘最新的元数据状态。这个操作完成之后,会把最新状态重新写到FsImage,并且清空EditLog, 主节点启动成功并进入正常运行以后,HDFS的更新操作都会被写入到EditLog,这是因为对于分布式文件系统而言,Fsimage文件通常都很庞大,如果所有的更新操作都直接往Fsimage文件中添加的话,那么系统会变得非常缓慢。【理解为merge】
从节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者主节点的调度来进行数据的存储和检索,并且向主节点定期发送自己所存储的块的列表。每个从节点的数据会被保存在各自节点的本地文件系统中。
SecondaryNameNode
hdfs存储原理—数据的存储冗余
未来保证系统的容错性和可用性。hdfs采用多副本存储方式对数据进行冗余存储,通常一个数据块的多个副本会被分到不同的从节点上。优点如下:
1、加快数据传输速度;
2、容易检查数据错误;
3、保证数据的可靠性。
此外,冗余存储中,例如有三个副本,那么一个保存在本地,一个保存在同一机架的DataNode,还有一个保存在不同机架的DataNode.
hdfs存储原理—数据存取策略
#存取策略总结: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集群中的主节点发送写请求,主节点就返回一个可写入的从节点的列表,再写入。
hdfs存储原理—hdfs数据读写过程
1、客户端通过调用FileSystem对象的open()来读取希望打开的文件。对于HDFS来说,这个对象是分布式文件系统的一个实例。
2、DistributedFileSystem通过RPC来调用namenode,以确定文件的开头部分的块位置。对于每一块,namenode返回具有该块副本的datanode地址。此外,这些datanode根据他们与client的距离来排序(根据网络集群的拓扑)。如果该client本身就是一个datanode,便从本地datanode中读取。DistributedFileSystem 返回一个FSDataInputStream对象给client读取数据,FSDataInputStream转而包装了一个DFSInputStream对象。
3、接着client对这个输入流调用read()。存储着文件开头部分块的数据节点地址的DFSInputStream随即与这些块最近的datanode相连接。
4、通过在数据流中反复调用read(),数据会从datanode返回client。
5、到达块的末端时,DFSInputStream会关闭与datanode间的联系,然后为下一个块找到最佳的datanode。client端只需要读取一个连续的流,这些对于client来说都是透明的。
1、客户端通过在DistributedFileSystem中调用create()来创建文件。
2、DistributedFileSystem 使用RPC去调用namenode,在文件系统的命名空间创一个新的文件,没有块与之相联系。namenode执行各种不同的检查以确保这个文件不会已经存在,并且在client有可以创建文件的适当的许可。如果检查通过,namenode就会生成一个新的文件记录;否则,文件创建失败并向client抛出一个IOException异常。分布式文件系统返回一个文件系统数据输出流,让client开始写入数据。就像读取事件一样,文件系统数据输出流控制一个DFSOutputStream,负责处理datanode和namenode之间的通信。
3、在client写入数据时,DFSOutputStream将它分成一个个的包,写入内部队列,称为数据队列。数据流处理数据队列,数据流的责任是根据适合的datanode的列表要求namenode分配适合的新块来存储数据副本。这一组datanode列表形成一个管线————假设副本数是3,所以有3个节点在管线中。
4、数据流将包分流给管线中第一个的datanode,这个节点会存储包并且发送给管线中的第二个datanode。同样地,第二个datanode存储包并且传给管线中的第三个数据节点。
5、DFSOutputStream也有一个内部的数据包队列来等待datanode收到确认,称为确认队列。一个包只有在被管线中所有的节点确认后才会被移除出确认队列。如果在有数据写入期间,datanode发生故障, 则会执行下面的操作,当然这对写入数据的client而言是透明的。首先管线被关闭,确认队列中的任何包都会被添加回数据队列的前面,以确保故障节点下游的datanode不会漏掉任意一个包。为存储在另一正常datanode的当前数据块制定一个新的标识,并将该标识传给namenode,以便故障节点datanode在恢复后可以删除存储的部分数据块。从管线中删除故障数据节点并且把余下的数据块写入管线中的两个正常的datanode。namenode注意到块复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接收处理。只要dfs.replication.min的副本(默认是1)被写入,写操作就是成功的,并且这个块会在集群中被异步复制,直到其满足目标副本数(dfs.replication 默认值为3)。
6、client完成数据的写入后,就会在流中调用close()。
7、在向namenode节点发送完消息之前,此方法会将余下的所有包放入datanode管线并等待确认。namenode节点已经知道文件由哪些块组成(通过Data streamer 询问块分配),所以它只需在返回成功前等待块进行最小量的复制。
hdfs存储原理—数据错误和恢复
主节点出错的恢复
1、将主节点上的元数据信息同步存储到其他文件系统中;
2、运行一个第二主节点,当主节点宕机以后,可以利用第二从节点来弥补,进行数据恢复。
从节点出错的恢复
每个从节点都会定期向主节点发送信息,报告自己的状态。当从节点故障时,就会被标记为宕机,这个时候主节点就不会再给它们发送IO请求。这个时候,如果发现某些数据块数量少于冗余因子,就会启动数据冗余复制,为它生成新的副本。
数据出错的恢复
客户端在读取数据后,会采用md5和sha1对数据进行校验,以确保读取到正确的数据。如果发现错误,就会读取该数据块的副本。
2.分布式文件系统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的原因,基于最佳传输损耗理论!
#延伸
如果公司使用的是固态硬盘,写的速度是300M/S,将块大小调整到 256M
如果公司使用的是固态硬盘,写的速度是500M/S,将块大小调整到 512M
Hdfs块大小分块细节
#HDFS块大小设置原则1)当hdfs的块太小,会增加寻址时间,程序一直在找块的开始位置。
2)当hdfs的块太大,1)太大会使得传输时间加长。从磁盘传输数据的时间就会明显大于定位这个块开始位置所需要的时间。导致程序在处理这块数据时,非常慢。 2)因为通常MapReduce中的Map任务一次只处理一个块中的数据,如果启动的任务太少,就会降低并行处理的速度
3)hdfs的块大小设置 主要取决于磁盘的传输速率(小公司磁盘差,设置128M。 大公司磁盘6,设置256M)。(切记)
#块太大或者太小的缺点实例
不能太大:
当前有文件a, 1G
128M一块 1G存8块 , 取第一块
1G一块 1G存1块 , 取第一块
只需要读取a文件0-128M部分的内容
①在一些分块读取的场景,不够灵活,会带来额外的网络消耗
②在上传文件时,一旦发生故障,会造成资源的浪费
不能太小:
文件a,128M
1M一块: 128个块,生成128个块的映射信息
128M一块, 1个块,一个块的映射信息
①块太小,同样大小的文件,会占用过多的NN的元数据空间
②块太小,在进行读写操作时,会消耗额外的寻址时间
#HDFS分块目的
减少后续MapReduce程序执行时等待文件的读取时间。【HDFS支持大文件存储,如果文件过大10G不分块在读取时处理数据时就会大量的将时间耗费在读取文件中,分块可以配合MapReduce程序的切片操作,减少程序的等待时间;】
#HDFS小文件问题处理
HDFS中文件上传会经常有小文件的问题,每个块大小会有150字节的大小的元数据存储namenode中,如果过多的小文件每个小文件都没有到达设定的块大小,都会有对应的150字节的元数据,这对namenode资源浪费很严重,同时对数据处理也会增加读取时间。所以解决这个问题有三个方法:
(1)采用har归档方式,将小文件归档
(2)采用CombineTextInputFormat
(3)有小文件场景开启JVM重用;如果没有小文件,不要开启JVM重用,因为会一直占用使用到的task卡槽,直到任务完成才释放。
JVM重用可以使得JVM实例在同一个job中重新使用N次,N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间
3.yarn分布式计算架构
1.组件角色
1.ResourceManager
1).整个集群同一时间提供服务的只有一,负责集群资源的统一管理和调度
2).处理客户端的请求,提交一个进程或杀死一个进程等
3).监控我们的NodeManager,一旦某个NodeManager挂掉,那么该NM上运行的任务需要告诉我们的ApplicationMaster如何进行处理
2.NodeManager
1).整个集群中有多个NM,负责自己本身节点的资源管理和使用
2).定时向ResourceManager汇报本节点的资源使用情况
3).接受并处理来自ResourceManager的各种命令
4).处理来自ApplicationManager的命令
5).单个节点的资源调度
3.ApplicationMaster
1).每个应用程序对应一个ApplicationMaster
2).为应用程序向ResourceManager申请资源(core、memory)分配给内部task
3).需要与NodeManager通信:启动、停止task,task是运行在container里面,AM也是运行在container里面的
4).ApplicationMaster相当于RM和NM之间的中介,必须经过他进行调度,通过任意一个NodeManager启动,RM向他分配任务,AM分配给各个NM
4.Container
1).封装了CPU、Memory等等资源的一个容器
2).是一个任务运行环境的抽象Maptask,Reducetask
3).在这里面运行
2.流程架构
步骤说明:
1)MR程序提交到客户端所在节点。
2)客户端ResourceManager申请一个application进程
3)ResourceManager给客户端返回一个 application路径
4)客户端向指定路径提交资源
5)4.完成之后,向RM申请运行mrAppMaster(ApplicationMaster)6)RM将用户的请求初始化一个task,按照资源调度器进行分发,任务随机发送给其中一个nodeManager,并在改nodeManager上创建mrAppMaster(MrAppMaster只有一个)
7)NodeManager接收到任务后,创建container容器,将job所需的资源下载到本地。
8)1.mrAPPManager向RM申请maptaskr容器,2.RM将运行maptask任务分配给其他的NodeManager, 3.其他NodeManager分别领取任务并创建container容器。
9)RM向其他接收到任务的NM发生程序启动脚本,这两个NM分别启动maptask,执行完maptask之后,maptask对数据分区排序。
10)所有的maptask执行完毕之后,mrAppMaster向RM申请容器运行reduce task
11)reduce task向maptask获取相应分区的数据。
12)reducetask运行完毕之后,会注销自己。
4.MapReduce原理
1.mapreduce工作流程
分片,格式化数据源
输入 Map 阶段的数据源,必须经过分片和格式化操作。
#分片操作:
指的是将源文件划分为大小相等的小数据块( Hadoop 2.x 中默认 128MB ),也就是分片(split),
Hadoop 会为每一个分片构建一个 Map 任务,并由该任务运行自定义的 map() 函数,从而处理分片里的每一条记录;#格式化操作:
将划分好的分片(split)格式化为键值对<key,value>形式的数据,其中, key 代表偏移量, value 代表每一行内容。
执行MapTask
每个 Map 任务都有一个内存缓冲区(缓冲区大小 100MB ),输入的分片(split)数据经过 Map 任务处理后的中间结果会写入内存缓冲区中。
如果写人的数据达到内存缓冲的阈值( 80MB ),会启动一个线程将内存中的溢出数据写入磁盘,同时不影响 Map 中间结果继续写入缓冲区。
在溢写过程中, MapReduce 框架会对 key 进行排序,如果中间结果比较大,会形成多个溢写文件,最后的缓冲区数据也会全部溢写入磁盘形成一个溢写文件,如果是多个溢写文件,则最后合并所有的溢写文件为一个文件。
执行shuffle过程
MapReduce 工作过程中, Map 阶段处理的数据如何传递给 Reduce 阶段,这是 MapReduce 框架中关键的一个过程,这个过程叫作 Shuffle 。
Shuffle 会将 MapTask 输出的处理结果数据分发给 ReduceTask ,并在分发的过程中,对数据按 key 进行分区和排序。
执行reduceTask
输入 ReduceTask 的数据流是<key, {value list}>形式,用户可以自定义 reduce()方法进行逻辑处理,最终以<key, value>的形式输出。
写入文件
MapReduce 框架会自动把 ReduceTask 生成的<key, value>传入 OutputFormat 的 write 方法,实现文件的写入操作。
至此,关于大数据hadoop组件角色原理介绍就讲完了, 关于hdfs,yarn,mapreduce仅仅了解这些还是不够的,但是作为认识hadoop对它进行一场懵懂的认知,我觉得是足够了。下期预计给大家交流关于hadoop优化配置方面的话题。
大喊一生"优雅~"
完。
版权归原作者 大宁哥 所有, 如有侵权,请联系我们删除。