shuffle 洗牌
map 是一个进程 mapTask
reduce 是一个进程 reduceTask
MapReduce中只有这两种进程。shuffle是存在于这两种进程之间的一个过程,shuffle可以分为map端的shuffle和reduce端的shuffle。
整体执行的流程:
1.根据分片规则划分不同的节点执行。
2.每个节点接受到数据,按照mapper代码分割成最小数据单元并发送出去。
3.发送出去的数据进入内存中的环形缓冲区(100M,达到80%的时候产生溢写)
4.溢写到磁盘缓冲区,在这里分区(partitioner),排序(sort),可能进行合并(combiner)操作
5.reduce端的shuffle主动向map端磁盘缓冲区索取数据。
6.将取回的数据进行分组(key相同的为一组)
7.数据进入自己编写的reducer代码中,通过代码对序列类型的value进行操作。
8.把最终的结果写入到文件中。
总结:
- reducer端有分组过程,所有进入reducer的数据的value值是序列类型
- 由于shuffle有排序,所有经过MapReduce操作的结果的key一定是有序的。
分区:map端shuffle中执行的过程。
对数据按照某一种条件进行分区,然后不同的节点的同一种分区的数据,会进入到同一个reduce节点中。
分区数要小于等于reducetask的数量
特殊情况:当分区数不限,reduceTask数量为1,所有分区的数据全部进入这个reduceTask中
MapReduce源码中的默认分区规则:
public class HashPartitioner<K, V> extends Partitioner<K, V> {
/** Use {@link Object#hashCode()} to partition. */
public int getPartition(K key, V value,
int numReduceTasks) {
**return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;**
}
return (key.hashCode() & Integer.MAX_VALUE)相当于是一个随机数,随机数和reduceTask的数量来取余,余数是0~(reduceTask-1)
默认reduceTask为1.