MapReduce确保每个Reducer的输入都是按键排序的,系统执行排序,将map输出作为输入传给Reducer的过程被称为shuffle。
MAP端
map函数开始产生输出时,并不是简单地将它写到磁盘上。这个过程更复杂,它利用缓冲的方式写到内存并出于效率的目的进行预排序。
每个map任务都有一个环形缓冲区用于存储任务输出。在默认情况下,缓冲区的大小为100MB,这个值可以通过mapreduce.task.io.sort.mb
属性来调整。一旦缓冲内容达到阈值(mapreduce.map.sort.spill.percent
,默认为80%),一个后台线程便开始把内容溢写(spill)到磁盘,在溢写到磁盘的过程中,map输出继续写道缓冲区,但如果在此期间缓冲区被写满,map会被阻塞直到磁盘过程完成。溢写过程按轮询方式将缓冲区的内容写到mapreduce.cluster.local.dir
属性在作业特定子目录下的指定的目录中。
在写磁盘之前,线程首先根据数据最终要传的reducer把数据划分成相应的分区(partition,用户也可自定义分区函数,但默认的partitioner通过哈希函数来分区,也很高效)。在每个分区中,后台线程按键进行内存中排序,如果有一个combiner函数,它就在排序后的输出上运行。运行combiner函数使得map输出结果更紧凑,因此减少写到磁盘的数据和传递给reducer的数据。
每次内存缓冲区达到溢出阈值时,就会新建一个溢出文件(spill file),因此,在map任务写完其最后一个输出记录后,会有几个溢写文件。在任务完成之前,溢写文件被合并成一个已分区且已排序的输出文件。配置属性是mapreduce.task.io.sort.factor
控制着一次最多能合并多少流,默认值是10.
如果至少存