这是我参与「第四届青训营」笔记创作活动的第八天。
Shuffle
Shuffle需求的产生
在MapReduce框架中,Shuffle起到在Map阶段和Reduce阶段间进行数据交换的作用,Shuffle过程往往伴随着大量的磁盘和网络IO,因此对其进行优化在系统性能优化中起到重要作用。
在Spark中,在存在宽依赖,即父RDD的分区可能对应多个子RDD的分区时便需要进行Shuffle操作。
常见的产生Shuffle的算子
Shuffle方式
Hash-Based Shuffle
通过对数据的主键计算得到hash值,再对下游reduce算子的数量取模便得到了数据所属的分区。
优缺点
优点 相较于sort shuffle减少了排序带来的内存等资源消耗 缺点
- 基于Hash的shuffle的实现方式中,生成的中间文件的个数会依赖于reduce阶段的Task个数
- 数据拉取时大量的网络IO
- 大量的随机读写增大了磁盘开销
Sort-Based Shuffle
优缺点
优点
- 产生的小文件较少
- 可伸缩性好 缺点
- 当map阶段的task数量量巨大时也会产生很多小文件
- 排序带来大量的性能消耗
- 强制对数据进行排序,即使并不需要
bypass机制
对于很多不需要sort的操作通过bypass机制进行shuffle
Shuffle Handle Shuffle Writer
External Shuffle Service
在各个节点上存在的ESS agent为下游的Shuffle Reader提供服务优化了Spark作业资源利用。
BypassMergeShuffleWriter
zero copy
通过DMA(Direct Memory Access)技术,不通过CPU而直接与内存进行数据交换,减少了数据copy
Netty zero copy
- 可使用堆外内存减少了从堆内到堆外的数据拷贝
- CompositeByteBuf、Unpooled.wrappedBuffer、ByteBuf.slice等对数组进行合并、包装或切分,减少了数据拷贝
- 可以直接将数据发送到对方channel,减少了内核态缓冲到用户态缓冲间的数据拷贝
Shuffle 优化
- broadcast 避免shuffle 小表join大表时,将小表广播到其他节点上
- 使用可以进行map-side预聚合的算子
Push Shuffle
- 通过Spark driver协调整体的shuffle
- 在map task的shuffle writer结束后增加push-merge操作,将数据复制一份推到远程shuffle service上
- 不同的reduce task可以共享shuffle数据