HDFS组成架构
1)NameNode:就是Master,是一个主管,管理者
(1)管理HDFS的名称空间
(2)配置副本策略
(3)管理数据块映射信息
(4)处理客户端读写请求
2)DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作
(1)存储实际的数据块
(2)执行数据块的读写操作
3)Client:就是客户端
(1)文件切分。数据上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传
(2)与NameNode交互,获取文件的具体信息
(3)与DataNode交互,读取或写入数据
(4)Client提供一些命令来管理HDFS,例如NameNode格式化
(5)Client可以通过一些命令来访问HDFS,比如对HDFS的增删查改操作
4)SecondaryNameNode:并非NameNode的热备,当NameNode挂掉的时候,它并不能马上替换NameNode提供服务
(1)辅助NameNode,分担其工作,比如定期合并Fsimage和Edits,并推送给NameNode
(2)在紧急情况下,可辅助恢复NameNode
HDFS的块大小
dfs.blocksize 来规定 ,hadoop2.x/3.x默认大小为128m,1.x为64m
文件的寻址时间为10ms,满足条件寻址时间为传输时间的1%的时候此时效率最佳,则总花费时间为10 * 100 = 1000ms = 1s,磁盘传输的时间大约为100M/s,因此块大小设置为128m hdfs块大小取决于磁盘的传输速率
HDFS写数据流程
1:客户端通过DistributeFileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否存在,父目录是否存在
2:NameNode返回是否可以上传
3:客户端请求第一个Block上传到哪几个DataNode服务器上
4:NameNode返回三个节点,分别是n1,n2,n3
5:客户端通过FSOutputStream模块请求n1上传数据,n1收到请求后会继续调用n2,然后n2调用n3,直到将这个通信管道建立完成
6:n1,n2,n3逐级应答客户端
7:客户端开始向n1上传第一个Block,先从磁盘读取数据放到一个本地内存缓存中,以Packet为单位,n1收到后就会传给n2,接着n2传给n3,n1每传一个Packet就放入到一个应答队列等待应答
8:当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器
HDFS的读数据流程
1:客户端通过DistributeFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址
2:挑选一台DataNode(就近原则,随机挑选)服务器,请求读取数据
3:DataNode开始传输数据给客户端 (从磁盘里面读取数据输入流,以Packet为单位来做校验)
4:客户端以packet为单位接收,先在本地缓存,然后写入目标文件
MR中MapTask的工作机制
简单概述:
InputFile通过spilt被切割为多个文件,通过Record按行读取内容给map,数据被map处理完之后交给OutputCollect收集器,对其结果key进行分区,(默认hashPartitioner),然后写入buffer,每个mapTask都有一个内存缓冲区(环形缓冲区),存放着map的输出结果,当缓冲区快慢的时候需要将缓冲区的数据以一个临时文件的方式溢写到磁盘,当整个mapTask结束后再对磁盘中这个mapTask产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduceTask拉取。
详细步骤:
1.读取数据组件InputFormat (默认是TextInputFormat)会通过getSpilt() 方法对输入目录中的文件进行逻辑切片规划得到block,有多少个block就对应启动多个MapTask
2.将输入文件切分为block之后,由RecordReader 对象(默认是LineRecordReader)进行读取,以\n作为分隔符,读取一行数据,返回<key,value> key表示每行首字符偏移值,value为这一行文本内容
3.读取block返回<key,value>,进入用户自己继承的Mapper类中,执行用户重写的map函数,RecordReader读取一行这里调用一次
4.Mapper逻辑结束之后,将Mapper的每条结果通过context.write进行collect数据收集。在collect中,会先进行分区处理,默认使用HashPartitioner
5.接下来,会将数据写入内存,内存中的这片区域叫做环形缓冲区,缓冲区的作用是批量收集Mapper结果,减少磁盘IO的影响。我们的Key/Value对以及Partition的结果都会被写入缓冲区。当然,写入之前,Key与Value都会被序列化成字节数组
6.当环形缓冲区的数据达到溢写比例时,溢写线程启动,需要对这环形缓冲区中的内容的Key进行排序
7.合并溢写文件,每次溢写会在磁盘上生成一个临时文件,如果Mapper的结果很大,又多次这样的溢写发生,磁盘上就会产生很多临时文件。当整个数据处理结束之后开始对磁盘中的临时文件进行Merge合并,因为最终的文件只有一个写入磁盘,并且为这个文件提供了一个索引文件,以记录每个reduce对应数据的偏移量
MR中ReduceTask的工作机制
简单描述:
Reduce 大致分为 copy、sort、reduce 三个阶段,重点在前两个阶段。
copy 阶段包含一个 eventFetcher 来获取已完成的 map 列表,由 Fetcher 线程去 copy 数据,在此过程中会启动两个 merge 线程,分别为 inMemoryMerger 和 onDiskMerger,分别将内存中的数据 merge 到磁盘和将磁盘中的数据进行 merge。待数据 copy 完成之后,copy 阶段就完成了。
开始进行 sort 阶段,sort 阶段主要是执行 finalMerge 操作,纯粹的 sort 阶段,完成之后就是 reduce 阶段,调用用户定义的 reduce 函数进行处理。
详细步骤:
Copy阶段:简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求maptask获取属于自己的文件(map task 的分区会标识每个map task属于哪个reduce task ,默认reduce task的标识从0开始)。
Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。
merge有三种形式:内存到内存;内存到磁盘;磁盘到磁盘。默认情况下第一种形式不启用。当内存中的数据量到达一定阈值,就直接启动内存到磁盘的merge。与map端类似,这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。内存到磁盘的merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的文件。
合并排序:把分散的数据合并成一个大的数据后,还会再对合并后的数据排序。
对排序后的键值对调用reduce方法:键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到HDFS文件中。
MR的Shuffle阶段
shuffle阶段分为四个步骤:依次为:分区,排序,溢写,分组,其中前三个步骤在map阶段完成,最后一个步骤在reduce阶段完成。
shuffle 是 Mapreduce 的核心,它分布在 Mapreduce 的 map 阶段和 reduce 阶段。一般把从 Map 产生输出开始到 Reduce 取得数据作为输入之前的过程称作 shuffle。
Collect阶段:将 MapTask 的结果输出到默认大小为 100M 的环形缓冲区,保存的是 key/value,Partition 分区信息等。
Spill阶段:当内存中的数据量达到一定的阀值的时候,就会将数据写入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了 combiner,还会将有相同分区号和 key 的数据进行排序。
MapTask阶段的Merge:把所有溢出的临时文件进行一次合并操作,以确保一个 MapTask 最终只产生一个中间数据文件。
Copy阶段:ReduceTask 启动 Fetcher 线程到已经完成 MapTask 的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上。
ReduceTask阶段的Merge:在 ReduceTask 远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。
Sort阶段:在对数据进行合并的同时,会进行排序操作,由于 MapTask 阶段已经对数据进行了局部的排序,ReduceTask 只需保证 Copy 的数据的最终整体有效性即可。