幸福的兔子

导航

MapReduce执行流程

 

一、执行流程
 HDFS --> InputFormat --> map --> shuffle --> reduce --> OutputFormat

 


二、详细介绍
 1、HDFS
  HDFS是hadoop文件存储系统,文件上传到hdfs时,会按照block块(hadoop1.0默认64M,hadoop2.0默认128M)进行切分,如果文件小于block不切分,大于block切分为n个block+剩余部分(小于block且不为0)。
  备注:不管是压缩文件还是非压缩文件都是按照block进行切分存储的;部分压缩文件不能被切割,如gzip。
  查看文件块的位置:hadoop fsck /file -files -blocks -locations -racks

 


 2、InputFormat
  MR框架基础类之一,包含两部分
       数据分割(inputSplit),hdfs上的数据是按block的,固定大小,不一定是固定行。实际上每个split包含后一个Block中开头部分的数据(解决记录跨Block问题)
  记录读取器(Record Reader),每读取一条记录,调用一次map函数,生成key,value对。key值是每个数据的记录在数据分片中字节偏移量,数据类型是LongWritable;value值是每行的内容,数据类型是Text。

 

 3、map
需自己写的函数,接收源数据,生成所需数据的key,value对

 

 4、shuffle
  Partion, Sort, Spill, Meger, Combiner,Copy, Memery, Disk……
  map的结果首先放到“环形内存缓存区”中进行partition(根据reduce的数目进行哈希算法,相同的key到一个分区),sort,当内存(默认大小100M 由io.sort.mb属性,超过80%由io.sort.spill.percent属性控制)>80M时经过combiner(如果设置了)后spill溢写到硬盘,map结束后会产生很多小文件,需要合并这些文件,merge不断地进行排序和combiner操作,目的有两个:1.尽量减少每次写入磁盘的数据量;2.尽量减少下一复制阶段网络传输的数据量。最后合并成了一个已分区且已排序的文件。为了减少网络传输的数据量,这里可以将数据压缩,只要将mapred.compress.map.out设置为true就可以了。将生成的文件按照分区copy到相应的reduce的内存中并排序,缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中,最后合并溢出的文件,不断地进行排序和reduce操作,直到每个reduce合并为一个文件。

  Partitioner :
   决定数据由哪个Reducer处理,从而分区

  MemoryBuffer:
   内存缓冲区,每个map的结果和partition处理的key value结果都保存在缓存中
   缓冲区大小:默认100M
   溢写阈值:100M * 0.8 = 80M

 

  Spill:
   内存缓冲区达到阈值时,溢写spill线程锁住这80M的缓冲区,开始将数据写出到本地磁盘中,然后释放内存。每次溢写都生成一个数据文件。溢出的数据到磁盘前会对数据进行key排序sort,以及合并combiner,发送相同Reduce的key数量,会拼接到一起,减少partition的索引数量。

 

  Sort:
   缓冲区数据按照key进行排序

 

  Combiner:
   数据合并,相同的key的数据,value值合并,减少输出传输量
   Combiner函数事实上是reducer函数,满足combiner处理不影响{sum,max等}最终reduce的结果时,可以极大提升性能

 

  Spill & Sort:
   和map一样,内存缓冲满时,也通过sort和combiner,将数据溢写到硬盘文件中。
   Reduce端的缓存设置更灵活,此时reduce函数未运行,也可以占用较大的内存

 

 5、Reduce

  多个reduce任务输出的数据都属于不同的partition,因此结果数据的key不会重复。合并reduce的输出文件即可得到最终的结果。

 

 

posted on 2018-04-06 14:00  幸福的兔子  阅读(145)  评论(0)    收藏  举报