0x0 背景
map-reduce是hadoop自带的计算框架,虽然现在大多数项目已经不采用该框架进行计算(Spark等基于内存的计算框架效率更高),但是他的原理还是值得进行研究的。map-reduce框架核心就是shuffle的过程,下面记录一下关于shuffle的理解。
0x1 Map端Shuffle
首先看下Hadoop权威指南中的图片
针对一个map任务,可看到以下步骤:
1. 输入数据分块作为input输入到一个map任务
2. map任务处理完成后将结果输出到内存buffer中(这是一个环形缓冲区,大小默认为100M)
3. 在将结果溢出到磁盘之前,还要做三项重要的处理:
(1)分区(默认按照reducer的个数和key的hash值进行分区)
(2)排序(对每个分区内的数据按照key进行排序)
(3)如果用户定义了combiner,执行combiner
4. 一旦buffer中数据到达阈值(默认是buffer总大小的0.8),则将buffer的数据溢出到磁盘上,每次会生成一个spill文件。
5. 最后将各个文件merge为一个文件,如果该map任务生成的spill文件超过三个,还会再执行一次combiner。
0x2 Reduce端Shuffle
依然先看图片:
从之前的map端图片可以看到,每个map生成的结果文件被分为N个分区,每个区对应一个reducer。
一旦一个map任务完成,各个reducer会将该map输出的文件中对应的分区拷贝过来,然后reducer端会有一个后台线程将这些文件merge为一个文件(如果文件数过多,往往需要merge好几轮),并且在merge的过程中会进行排序。那么reducer是如何知道什么时候去哪台节点获取自己的partition呢?原文给出答案:
How do reducers know which machines to fetch map output from?
As map tasks complete successfully, they notify their application master using the heartbeat mechanism. Therefore,
for a given job, the application master knows the mapping between map outputs and hosts. A thread in the reducer
periodically asks the master for map output hosts until it has retrieved them all.