一,HDFS文件写入流程
hadoop fs -put word.txt /input 执行该步骤的流程:
1,客户端先与NameNode通信,通过RPC通信,创建一个远程的RPC请求,发起上传一个文件请求,
2,NameNode接收到这个请求之后,会对新建文件的进行各种检查,确保这个文件在HDFS中是不存在的,以及客户端有新建文件的权限,
3,NameNode在所有检查完成之后,向客户端返回允许写文件的消息
4,客户端接收到该消息之后,会把文件流式的写入到客户端本地的文件系统的一个临时文件中。
客户端将文件切分成块,每块128M
5, 当这个临时文件达到128M时,也就是一个Block块大小时,客户端会先上传第一个Block,发起上传的请求,
6, 当NameNode接收到这个请求时,会在DataNode信息池中检查DataNode信息,确定哪些可以保存以及备份该Block块的DataNode列表.
7, NameNode会返回可以保存以及备份该Block块的DataNode列表信息,
8,客户端接收到返回列表信息之后,会与第一个DataNode创建连接,并请求第一个DataNode创建与这组DataNode列表的信息流管道。
会向第一个DataNode请求建立Block传输通道通道:
9,创建完信息流通道之后,客户端会以数据包packet为单位发送数据,每个packet时4k,按照流式的方式写入到数据管道中,,
首先将数据包packet写入到第一个DataNode中,当数据包写入到第一个DataNode磁盘的时,会将数据包通过构建的信息流管道,发送到第二个DataNode中,之后,当数据包写入到第二个DataNode磁盘时,会将数据包通过构建的信息流管道,发送到第三个DataNode中,此时这个数据包就以数据流管道的形式完成了在HDFS的保存与备份,这样完成了一个数据包的保存与备份。
9.1 9.2 最后一个DataNode保存数据包成功之后,会通过信息流管道返回成功信息给前一个DataNode。
如node03保存成功的确认信息发回给node02,node02保存成功的信息返回给node01,最后node01会返回给客户端,
这样通过流式的传输,并逐级调用,当完成数据流的传输之后,该Block块也在HDFS中保存与备份成功。
10, 之后客户端会给NameNode发送最终的写入成功的信息,这时第一个Block就传输完成,
11,接下来会传输第2个Block块,重复4-10,最终完成该文件的传输。
二, HDFS文件读取流程
1,客户端请求读取文件
2.1,检查HDFS目录树
2.2,查询文件组成,查询块与DataNode的映射关系
3,安装DataNode与客户端的距离由近到远的列表返回给客户端
4,客户端与最近的DataNode连接,
5,返回给客户端的Block数据
6,客户端组装文件的Block成一个文件。
三,HDFS文件操作与管理
Hadoop服务脚本:
sbin目录:
start-all.sh/stop-all.sh 启动/停止Hadoop集群中全部服务(HDFS服务和YARN服务)
start-dfs.sh/stop-dfs.sh 只启动/停止HDFS相关全部服务(NameNode,DataNode,JournalNode)
hadoop-daemon.sh start/stop namenode/datanode/journalnode 单独启动/停止单台HDFS某个服务
start-yarn.sh/stop-yarn.sh 启动/停止YARN相关全部服务(ResourceManager,NodeManager)
yarn-daemon.sh start/stop resourcemanager/nodemanager 单独启动/停止单台YARN某个服务
bin/hadoop fs或者bin/hdfs dfs
四, YARN程序运行流程
1,客户端提交作业请求
2,ResouceManager先给客户端返回一个作业id,接着会要求一个NodeManager启动一个Container来启动该作业的ApplicationMaster,ResourceManager会监控ApplicationMaster的运行状态。
3,ApplicationMaster会先计算这个作业需要多少个map,多少个reduce,运行这些任务,需要多少cpu,mem,之后ApplicationMaster会向ResoureManager注册,注册成功之后会为客户端的作业申请资源。
4,当ResourceManager将资源分配给ApplicationMaster之后,ApplicationMaster会查看这些资源包含是哪些NodeManager来提供的,然后会和相应的NodeManager进行通信,在相应的节点上启动Container,并且启动相应的任务。运行在Container中的任务会向ApplicationMaster及时的汇报当前的状态和进度。
5,在这些作业的任务运行时,客户端会通过ResourceManager获取Applicationmaster的通信地址,然后客户端会与Applicationmaster进行通信,周期性的可以获取到作业所有任务的运行状态与进度。当作业的任务完成之后,整个作业就结束了,Applicationmaster会向ResourceManager申请注销,并释放申请的计算资源。
五, MapReduce原理与编程模型
MapReduce简介
源自Google的MapReduce的论文,发表于2014年12月
是一个批处理框架
一个MapReduce程序分为Map阶段和Reduce阶段
特性:
易于编程
良好的扩张性
高容错性
适合海量数据的离线处理,GB,TB,PB
擅长的场景:
数据统计,如网站的PV,UV统计,Map和Reduce
搜索引擎索引,产生的背景,Baidu,Google都使用MapReduce进行索引
海量数据查找,分布式计算与查找,将一个TB的文件,拆分到各个节点下去查找,即分布式查找
复杂数据分析算法实现,聚类,推荐算法,
不擅长的场景:
低延迟实时计算:需要ms级别返回结果
流式计算:数据像流水一样,过来一个处理一个,然后MapReduce只能处理静态的数据,像HDFS内存储的Block块的数据,不是实时变化的。
MapReduce的执行流程
现实案例:
具体的执行流程:
步骤:分解--> 合并求解
分-Map
数据分块存储
负责问题分解成多个简单任务
合-Reduce
把Map的输出结果作为输入合并求解。
整体过程:
Map阶段:
文件被保存到HDFS会被切分并保存成一个个的Block块的形式,MapReduce通过InputFormat接口读取HDFS上的Block块,对Block进行逻辑分片Split,每个Block块对应一个Split片(Block0- > Split0),即逻辑分片Split,每个Map Task处理一个Split片(Block0->Split0->Mapper0),对这个Block进行分解,输出的是以Key-Value对的形式
Partitioner阶段:
将输出结果给partitioner进行分区,确定去哪个Reduce Task,具体是将输出的Key取一个Hash值,将这个Hash值对Reduce的个数取余数
R_counts是Reduce Task的个数,hash(key) % R_Counts,这个余数就是对应的哪个Rdeuce Task来处理这个Map Task的输出结果。
Reduce阶段:
Reduce阶段会先将这些Partitioner分给的数据中进行Shuffle和Sort,然后再汇总,通过OutPutFormat接口输出到HDFS文件系统上。
各个阶段详解:
InputFormat:
处理的问题:
- 文件分片(InputFormat)方法:
- 处理跨行问题
将分片数据分析成key/value对
- 默认实现是TextInputFormat
TextInputFormat
- key是行在文件中的偏移量,Value是行内容
- 如果一行被截断,则读取下一个Block的前几个字符
Spilt
Block:
- HDFS中最小的数据处理单元
- 默认为128M
Split:
- MapReduce中最小的计算单元
- 默认与Block一一对应
Blcok与Split
- Split与Block的对应关系是任意的,可由用户控制。
Partitioner
Partitioner决定了Map Task输出的每一条数据交给哪个Reduce task处理
默认实现:HashPartitioner
- Hash(key) mod R
- R是Reduce Task数量
- 分区计算结果产生的分区号等于Reduce Task号
允许自定义分区
Shuffle的过程:
MapReduce处理的是HDFS上的file文件,并通过InputFormat(默认是TextInputFomat)将文件file的文本数据输入到Map任务中的Map方法,Map方法接收到Key-Value对的形式数据,会将数据保存到本地磁盘当中。在写入磁盘之前还会有一个阶段,就是这个Shuffle的过程,即从Map写出数据开始,到整个Map任务执行完成。在Reduce阶段也会有Shuttle的过程。Shuffle过程开始是从Map阶段输出开始的,Map的输出结果的数据,Map首先会把输出的数据写入到内存缓存区,在内存中会划分出一块100M的内存缓冲区,也叫环形缓冲区。这个缓冲区默认大小时100M,它也可通过配置文件来设置其大小。Map任务只要处理完结果,首先会先将数据写入到这个环形缓冲区,当缓冲区的被写入的数据达到80%时,Map会把缓冲区的数据写入到本地磁盘文件当中,在从缓冲区写入到本地磁盘的过程中,Map会继续向这个缓冲区写入其输出的数据,像这种一边往缓冲区里写数据,一遍从缓冲区溢出写入到磁盘的过程,就像是环状,所以叫该缓冲区为环形缓冲区,其实在内存中就是一个数组数据。从环形缓冲区往磁盘写数据之前,在内存当中,会调用partitioner会对数据进行分区,在分区内,会按照key进行快速排序,排序完成,会将内存中的数据写入到文件中,因为在内存中的数据是有序的,所以在分区内,写入到磁盘中文件的数据也是有序的,随着MapTask输出多个文件,这个些文件是分区的,并且分区内是有序的,当MapTask运行完成之后,会将所有输出的小文件,合并并排序,并且在分区内有序。合并并排序完之后,Map阶段的Shuffle阶段就结束了,然后就进入到Reduce的Shuffle阶段,Reduce会在所有Map Task输出的文件当中,通过网络,下载选择属于自己的分区数据,当拷贝完成之后,会Reduce端会将这些数据进行合并,在合并的过程当中,会将相同key的数据分到一组,不同的key之间进行排序,最终会形成一个key对应一组值,默认会通过key字典的升序进行排序。每组数据会调用一次重写的Reduce方法,当其处理完数据之后,会通过OutputFormat接口的实现类(默认是TextOutputFormat)将数据学出到HDFS磁盘中。
Shuffle的过程总结:
每个Map Task把输出结果写到内存中的环形缓冲区
当内存环形缓冲区写入的数据量达到一定阈值时,后台线程会把数据溢写到磁盘中
根据partitioner,把数据写入到不同的partition。
对于每个partition的数据进行排序。
随着Map Task的不断运行,磁盘上溢出的文件越来越多
将这些溢出的文件合并
对于一个partition下的不同分片,使用递归排序,同一分区的数据有序
Reduce Task通过网络远程拷贝Map Task的结果文件中属于它的分区数据
合并所有已拷贝过来的数据文件
采用归并排序算法,对文件数据内容整理排序,将相同key的数据分为一组,不同key之间有序排序
最终生成一个key对应一组值的数据集,一个key对应的一组数据会调用一次reduce方法
总体思想是:
先Map再Reduce,即先分类,再合并同类项。
Combiner优化:
Combiner总结:
Combiner调用的地方:
- MapTask的环形缓冲区向磁盘溢写文件之前调用Combiner
- Map阶段在合并本地多个文件写入一个大文件之前调用Combiner
使用Combiner好处:
- 减少Map Task输出数量,由于临时结果写入到本地磁盘,所以能够减少磁盘IO
- 减少Reduce-Map网络传输数据量,由于Reduce需要远程通过网络从Map拷贝数据,所以可以提高拷贝速度。
应用场景:
- 针对结果可以叠加的场景
- SUM可以但是Average不行
数据本地性:(Data locality)
数据本地性的含义
- 如果任务运行在与它需要处理的数据在同一个节点,则称该任务具有“数据本地性”
数据本地性级别:(由高到底)
- 同节点:Node-local
- 同机架:Rack-local
- 跨机架:off-switch
数据本地性优点
- 避免通过网络远程读取数据进而提高数据读取效率