shuffle简介
- MapReduce的shuffle一般是指Map输出到Reduce输入的整个过程。
- 整个shuffle过程中伴随着大量的磁盘IO , 网络IO 。
- shuffle性能的高低 , 直接决定了整个程序的性能高低 。
shuffle的字面意思是洗牌 , 即有序 - 无序的一个过程 , 比如JDK中的shuffle , 它的作用就是随机打乱集合中的元素 。但在MapReduce中 , 则更像是狭义shuffle的逆过程。
shuffle过程
- map task执行 , 输入源来自HDFS的block
- 数据经过mapper之后 , 得到键值对
- 如果在map task中想做键值对的合并 , 这个过程叫做combine(需要设置Combiner)
- 键值对序列化为字节数组后 , 被写入缓冲区
- 该缓冲区默认大小限制100M , 数据量较大的情况 , 溢出到磁盘 , 这个过程叫做spill , 磁盘可存在多个spill文件
- 当map task完成时 , 内存缓冲区的数据会被写入spill文件 , 所以最终磁盘中至少有一个spill文件
- 因为最终的spill只能有一个 , 所以需要将多个spill文件归并到一起 , 这个过程叫做merge
- 默认由系统选择发给哪个reduce task(可通过Partitioner接口自定义)
- 每个reduce task不断通过RPC从JobTracker获取map task是否完成的信息 , 如果reduce task得到通知 , 某台TaskTracker上的map task执行完成 , 则shuffle进入后半段
- copy阶段 , reduce task启动数据线程(fetcher) , 通过http方式请求map task所在的TaskTracker获取map task的输出文件。
- merge阶段 , 与map阶段的merge类似 , 最终生成一个spill文件
- reduce执行 , 完成后将结果集放到HDFS
shuffle优化
大部分map task和reduce task执行在不同的节点上 , 所以大量job的情况下 , 集群必然耗费大量的网络资源在IO上 。还有一小部分的map task和reduce task处于同一节点中 , 磁盘IO对job完成时间影响也较可观 。数据传输到reduce task之后 , 还需要进行排序 , 这部分工作所耗费的系统资源、时间也是不容忽略的。
根据以上情况 , 优化的方向大致可以分为 :
- 硬件层面
- 提高磁盘IO性能(固态硬盘)
- 提高网络IO性能(千兆网卡)
- 软件层面
- 合理分配资源
- map task和reduce task数量 , 通过benchmark找到较为合理的区间
- 减少map task传输到reduce task的数据(压缩数据)
- 减少磁盘IO(内存缓存)
- 配置noatime
- 尽可能地避免排序
- 合理分配资源