MapReduce基本框架

mapreduce 设置map端输出压缩方式 mapreduce的map_MapReduce

MapReduce计算模型的两个重要阶段:

  • Map:映射,将数据转化为键值对的形式。切片操作在集群中并发执行,切片大小默认取最大切片、最小切片、块大小(128M)中间值。
  • Reduce:规约,负责数据的计算合并。

shuffle作为Map和Reduce两端的衔接,是MapReduce的核心,分布在MapReduce的Mapper端和Reducer端,主要包含以下几个阶段:

Collect阶段

将Map任务输出的“键-值对”数据存储到内存中的环形缓冲区。等待缓冲区满到一定阈值(如80%)触发Spill,将数据转存到磁盘。

在环形缓冲区内,设置了索引数据和Partition分区信息。数据区域和索引区域在缓冲区中是相邻不重叠的两个区域,通常使用一个分界点来划分。数据的存储方式是向上增长,索引数据的存储方式是向下增长。初始的分界点是0,之后在每次Spill之后都会更新一次,重定位到空闲区域的中间位置。

分区规则是对key进行哈希(或者随机)取模分区,分区数通常为reduce的个数。
Sort阶段:将缓冲区的数据按照Partition值和Key关键字进行排序,只需要移动索引数据。排序结果是缓冲区中的数据按照Partition为单位聚集在一起,同一Partition内的数据按照Key有序。

Combiner阶段

可选的,分区内部相同key数据的合并或处理,如词频统计或者求最大值,来减少拷贝到reduce的文件,主要的性能提升在于网络开销

Spill阶段

根据排序后的索引,将缓冲区的Partition逐个转存到文件中。为了定位每个Partion在文件中的位置,设置三元组(起始位置、原始数据长度、压缩数据长度)索引存储到索引文件。

Merge阶段

将所有Spill出来的临时文件(数据和索引)进行聚合(我理解就是归并排序)。此时Map任务已经结束,内存已有空闲。

Copy阶段

Reduce任务通过HTTP到已经完成Map任务的节点上拷贝数据。默认保存在内存的缓冲区,当内存的缓冲区达到一定的阈值时,就会将数据写到磁盘上。

Merge Sort阶段

Merge操作通常是跟Copy操作同时进行,在后台开启两个线程对内存到本地的数据文件进行合并排序操作。分组默认是将相同的key的value放在一起。作用是为了reduce函数更好的计算相同key值出现的次数。

相关的问题理解

Mapper和Reducer的数量

Mapper的数量通常由切片数量决定,与文件大小和数量,以及切片大小有关,不能人为设定;而Reduce的数量可以自己设置。

数据倾斜

数据倾斜是由于partition分区时会将相同键值的数据分配到同一个partition,导致存在部分reduce需要处理非常多的数据。

解决方案是根据实际数据的特点自定义partition分区的规则。

MapReduce优化思路

  • 小文件事先合并成大文件,减少“边角料”式的切片,充分利用计算资源(可能是HDFS的操作,切片时候需要注意的
  • 环形缓冲区批量收集map结果,可以减少磁盘IO,可以增大缓冲区容量或者阈值。
  • 对Map输出的数据进行压缩,减少网络传输和磁盘IO带来的性能损耗
  • 避免Reduce端出现数据倾斜,自定义partition规则;
  • 自定义conbiner,及时归并spill出来的文件;
  • 集群优化的核心思路是减少磁盘IO和网络读写(在实际经验中分布式系统运行的瓶颈一般都是IO而不是CPU),例如、对Map输出的数据进行压缩等。

Combiner和Reduce的区别

combiner发生在map端,处理一个任务中的文件数据,不能跨map任务;reduce可以接收多个map任务进行处理。

Shuffle是必需的吗?

不是的,只有在需要去重、聚合、排序、统计等操作时。不然的话可以不要(如求平均,降低计算和磁盘的性能损耗。