大数据Shuffle原理与实践 | 青训营笔记

69 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第15天

一.Shuffle概述

1.MapReduce概述

在Map、Shuffle、Reduce三个阶段

2.Map阶段

在单机上进行的针对一小块数据的计算过程

3.Shuffle

在map阶段的基础上,进行数据移动

4.Reduce

对移动后的数据进行处理,依然是在单机上处理一小份数据

image.png

5.Shuffle重要性

  • M*R网络连接
  • 大量的数据移动
  • 数据丢失风险
  • 可能存在大量的排序操作
  • 大量的数据序列化、反序列化操作
  • 数据压缩

二.Shuffle算子

1.Shuffle算子分类

  • Repartition(改变数据分区)
  • ByKey(给数据一个key,把hey相同的组合在一起)
  • join把数据放在一起
  • Distinct

2.Spark中对shuffle的抽象

  • 窄依赖:父RDD的每个分片至多被子RDD中的一个分片所依赖
  • 宽依赖:父RDD中的分片可能被子RDD中的多个分片所依赖

3.Shuffle Dependency构造-Partitioner

  • 两个接口:numberPartitions、getPartition
  • 经典实现:HashPartitioner

image.png

4.Shuffle Dependency构造-Aggregator

  • createCombiner:只有一个value的时候初始化的方法
  • mergeValue:合并一个value到Aggregator中
  • mergeCombiners:合并两个Aggregator

三.Shuffle过程

1.Hash Shuffle:

生成的和打开的文件太多,资源消耗多 优化:每个partition会映射一个文件片段

image.png

image.png

2.Sort shuffle(写数据)

每个task生成一个包含所有partition数据的文件

image.png

3.Shuffle(读数据)

每个reduce task分别获取所有map task生成的属于自己的片段

image.png

4.Shuffle过程的触发流程

Collect Action->SubmitJob->GetDependencies->RegisterShuffle image.png

5.Shuffle Handle的创建

Register Shuffle时做的最重要的事情是根据不同条件创建不同的shuffle Handle

image.png

6.Shuffle Handle与Shuffle Writer的对应关系

image.png

7.Write实现-BypassMergeShuffleWriter

  • 不需要排序,节省时间
  • 写操作的时候会打开大量文件
  • 类似于Hash Shuffle

8.Write实现-UnsafeShuffleWriter

  • 使用类似内存页存储序列化数据
  • 数据写入后不再反序列化

image.png

9.Writer实现-UnsafeShuffleWriter

  • 只根据partition排序Long Array
  • 数据不移动

image.png

10.Writer实现-SortShuffleWriter

  • 支持combine
  • 需要combine时,使用PartitionedAppendOnlyMap,本质是个HashTable
  • 不需要combine时PartitionedPairBuffer本质是个array

image.png

11.Reader实现-网络时序图

  • 使用基于netty的网络通信架构
  • 位置信息记录在MapOutputTracker中
  • 主要会发送两种类型的请求:OpenBlocks、Chunk、Stream

image.png

12.Reader实现-ShuffleBlockFetchLterator

  • 区分local和remote节省网络消耗
  • 防止OOM

image.png

13.Read实现-External Shuffle Service

ESS作为一个存在于每个节点上的agent为所有shuffle Reader提供服务,从而优化了Spark作业的资源利用率,MapTask在运行结束后可以正常退出

image.png

14.Zero Copy

  • 不使用zero copy

image.png

  • 使用sendfile

image.png

  • 使用sendfile+DMA gather copy

image.png

15.Netty Zero Copy

  • 可堆外内存,避免JVM堆外内存的数据拷贝
  • CompositeByteBuf、Unpooled.wrappedBuffer、ByteBuf.slice,可以合并、包装、切分数组,避免发送内存拷贝
  • Netty使用FileRegion实现文件传输,FileRegion底层封装了FileChannel#transferTo()方法,可以将文件缓冲区的数据直接传输到目标Channel,避免内核缓冲区和用户态缓冲区之间的数据拷贝

16.Shuffle优化

  • 避免shuffle
  • 使用broadcast替代join

image.png

  • 使用可以map-side预聚合的算子

image.png

17.shuffle倾斜优化

影响:

  • 作业运行时间变长
  • Task OOM导致作业失败

image.png 处理方法:

  • 提高并行度(简单,但不根治)

image.png

18.Spark AQE Skew Join

AQE根据shuffle文件统计数据自动检测倾斜数据,将那些倾斜的分区打散成小的子分区,然后各自进行join。

image.png