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

184 阅读3分钟

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

本节课主要学习内容如下:
1.Shuffle概述
2.Shuffle算子
3.Shuffle过程
4.Push Shuffle

shuffle概述

image.png

经典shuffle过程

  • map阶段
  • shuffle阶段
  • reduce阶段

为什么shuffle如此重要?
数据shuffle表示了不同分区数据交换的过程,不同的shuffle策略性能差异较大。目前在各个引擎中shuffle都是优化的重点,在spark框架中,shuffle是支撑spark进行大规模复杂数据处理的基石。

shuffle算子

shuffle算子分类

image.png

算子使用例子

val text = sc.textFile("mytextfile.txt")
val counts = text .flatMap(line => line.split(" "))
.map(word => (word,1))
.reduceByKey(+) counts.collect

Shuffle Dependency
  • 创建会产生shuffle的RDD时,RDD会创建Shuffle Dependency来描述Shuffle相关的信息
  • 构造函数
    - A single key-value pair RDD, i.e. RDD[Product2[K, V]],
    - Partitioner (available as partitioner property),
    - Serializer,
    - Optional key ordering (of Scala’s scala.math.Ordering type),
    - Optional Aggregator,
    - mapSideCombine flag which is disabled (i.e. false) by default.
  • Partitioner
    • 用来将record映射到具体的partition的方法
  • 接口
    • numberPartitions
    • getPartition
  • Aggregator
    • 在map侧合并部分record的函数
  • 接口
    • createCombiner:只有一个value的时候初始化的方法
    • mergeValue:合并一个value到Aggregator中
    • mergeCombiners:合并两个Aggregator

shuffle过程

shuffle发展历程

image.png

HashShuffle写数据

image.png

优化

image.png

Sort Shuffle写数据

image.png

Shuffle 读数据

image.png

  • HashShuffle
    • 优点:不需要排序
    • 缺点:打开,创建的文件过多
  • SortShuffle
    • 优点:打开的文件少、支持map-side combine
    • 缺点:需要排序
  • TungstenSortShuffle
    • 优点:更快的排序效率,更高的内存利用效率
    • 缺点:不支持map-side combine
Register Shuffle

由action算子触发DAG Scheduler进行shuffle register
Shuffle Register会根据不同的条件决定注册不同的ShuffleHandle

image.png

三种ShuffleHandle对应了三种不同的ShuffleWriter的实现

image.png

  • BypassMergeSortShuffleWriter:HashShuffle
  • UnsafeShuffleWriter:TunstonShuffle
  • SortSHuffleWriter:SortShuffle
ShuffleReader网络请求流程

image.png

ShuffleBlockFetchIterator

image.png

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

  • 防止OOM

    • maxBytesInFlight
    • maxReqsInFlight
    • maxBlocksInFlightPerAddress
    • maxReqSizeShuffleToMem
    • maxAttemptsOnNettyOOM
External Shuffle Service

image.png

为了解决Executor为了服务数据的fetch请求导致无法退出问题,我们在每个节点上部署一个External Shuffle Service,这样产生数据的Executor在不需要继续处理任务时,可以随意退出。

shuffle优化

避免shuffle ——使用broadcast替代join

image.png

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

image.png

Shuffle参数优化

image.png

倾斜优化

image.png

AQE Skew Join

image.png

  • 零拷贝

    • sendfile+DMA gather copy
  • Netty 零拷贝

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

Push Shuffle

shuffle过程存在哪些问题?
  • 数据存储在本地磁盘,没有备份
  • IO 并发:大量 RPC 请求(M*R)
  • IO 吞吐:随机读、写放大(3X)
  • GC 频繁,影响 NodeManager
Magnet主要流程

image.png

image.png

主要为边写边push的模式,在原有的shuffle基础上尝试push聚合数据,但并不强制完成,读取时优先读取push聚合的结果,对于没有来得及完成聚合或者聚合失败的情况,则fallback到原模式。

Cloud Shuffle Service架构

image.png

  • Zookeeper WorkerList [服务发现]

  • CSS Worker [Partitions / Disk | Hdfs]

  • Spark Driver [集成启动 CSS Master]

  • CSS Master [Shuffle 规划 / 统计]

  • CSS ShuffleClient [Write / Read]

  • Spark Executor [Mapper + Reducer]

Cloud Shuffle Service 读写流程

image.png

Cloud Shuffle Service 支持AQE

image.png

在聚合文件时主动将文件切分为若干块,当触发AQE时,按照已经切分好的文件块进行拆分。

总结:

通过本节课,我了解了Shuffle的概念,以及Shuffle的各种算子和内部的Shuffle依赖以及各种组件,学习了Shuffle的过程,以及Push Shuffle的思路。