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

152 阅读5分钟

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

本课程主要分为四个部分:

  1. shuffle概述:shuffle是什么,shuffle的基本过程是什么
  1. spark中的shuffle算子:学习使用spark中的会产生shuffle的算子,了解其基本特性
  1. spark中的shuffle过程:spark中shuffle的核心原理和实现细节
  1. Push based shuffle:push shuffle社区的实现方案以及字节自己的实现方案

MapReduce概述

image.png

map:将大量数据分成几份,分散在不同机器上处理,该过程称为分布式处理

shuffle:每份数据会有不同分颜色,我们要对不同数据分别处理,将相同颜色的数据放在一起

reduce:然后继续处理这几份数据

shuffle算子

shuffle算子分类:

image.png

repartition:重新改变分区

ByKey:给定一个key,把key聚合在一起的算子

join算子:把本身没有在一起的数据按照某种条件放在一起

Spark中对shuffle的抽象-宽依赖,窄依赖

image.png

image.png

shuffleDependency如何产生,在产生Cogroup后,cogroup 由调用fullOuterJoin,join产生

Shuffle Dependency

  • 创建会产生shuffle的RDD时,RDD会创建Shuffle Dependency来描述Shuffle相关的信息

  • 构造函数

    • A single key-value pair RDD, i.e. RDD[Product2[K, V]],一个key-value的RDD
    • Partitioner (available as partitioner property),给定义和k,创建一个叫k的分区
    • Serializer,把一个对象映射为一个数据流,或者相反操作
    • Optional key ordering (of Scala’s scala.math.Ordering type),k是否需要排序的flag
    • Optional Aggregator,
    • mapSideCombine flag which is disabled (i.e. false) by default.

Partitioner

image.png

Aggregator

image.png

shuffle过程

shuffle历史

image.png

Hash Shuffle - 写数据

image.png

写数据优化:

image.png

Sort Shuffle -写数据

image.png

Shuffle - 读数据

image.png

Shuffle过程的触发流程

image.png

以上图为例,当执行collect时,它是个action算子触发计算,在collect会调用我们的Spark中的Task scheduler的submitJob,在Task scheduler中会分析counts的依赖关系,在查找依赖关系时会创建shuffle RDD对象,这个对象Task scheduler调用GetDependencies时,就会真正去创建shuffleDependencies,然后向shuffleManager注册自己。 后续会生成两个stage:map,reduce,然后这两个stage会提交给Executor。

Shuffle Handle的创建

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

image.png

不同的shuffle Handle对应不同的shuffle Writer

image.png

BypasssMergeShuffleWriter

image.png

UnsafeShuffleWriter

image.png

image.png

SortShuffleWriter

image.png

Reader实现 网络时序图

image.png

reader 的执行流程中需要网络请求,网络传输如下:

image.png

Reader实现 - ShuffleBlockFetchIterator

image.png

Reader实现 - External Shuffle Service

目的:为了解耦数据计算和数据服务,Spark支持单独的服务来处理这些请求

image.png

image.png 在使用reduce读取时,访问网络获取shuffle数据的这一部分使用的是ESS。

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

在shuflle中时用到的技术:

Shuffle 优化使用的技术 - Zero Copy

image.png

减少用户态与内核态的切换,减少cpu拷贝

Netty 零拷贝

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

shuffle优化

  • 避免shuffle ——使用broadcast替代join

  • //传统的join操作会导致shuffle操作。
    //因为两个RDD中,相同的key都需要通过网络拉取到一个节点上,由一个task进行join操作。
    val rdd3 = rdd1.join(rdd2)
    
    //Broadcast+map的join操作,不会导致shuffle操作。
    //使用Broadcast将一个数据量较小的RDD作为广播变量。
    val rdd2Data = rdd2.collect()
    val rdd2DataBroadcast = sc.broadcast(rdd2Data)
    
    //在rdd1.map算子中,可以从rdd2DataBroadcast中,获取rdd2的所有数据。
    //然后进行遍历,如果发现rdd2中某条数据的key与rdd1的当前数据的key是相同的,那么就判定可以进行join。
    //此时就可以根据自己需要的方式,将rdd1当前数据与rdd2中可以连接的数据,拼接在一起(String或Tuple)。
    val rdd3 = rdd1.map(rdd2DataBroadcast...)
    
    //注意,以上操作,建议仅仅在rdd2的数据量比较少(比如几百M,或者一两G)的情况下使用。
    //因为每个Executor的内存中,都会驻留一份rdd2的全量数据。
    复制代码
    
  • 使用可以map-side预聚合的算子

  • Shuffle 参数优化

    • spark.default.parallelism && spark.sql.shuffle.partitions
    • spark.hadoopRDD.ignoreEmptySplits
    • spark.hadoop.mapreduce.input.fileinputformat.split.minsize
    • spark.sql.file.maxPartitionBytes
    • spark.sql.adaptive.enabled && spark.sql.adaptive.shuffle.targetPostShuffleInputSize
    • spark.reducer.maxSizeInFlight
    • spark.reducer.maxReqsInFlight spark.reducer.maxBlocksInFlightPerAddress
  • Shuffle 倾斜优化

    • 什么叫倾斜?有什么危害

    • 解决倾斜方法举例

      • 增大并发度
      • AQE

为什么要PUSH Shuffle?

  • 上一部分所讲的shuffle过程存在哪些问题?

    • 数据存储在本地磁盘,没有备份
    • IO 并发:大量 RPC 请求(M*R)
    • IO 吞吐:随机读、写放大(3X)
    • GC 频繁,影响 NodeManager

Magnet主要流程

image.png

Magnet实现原理

image.png

server合并数据的细节:

magnet server在给数据合并时会给每个partition维护一些原数据,这份原数据由applicaiton id,shuffle id和 partition id 混合而成。

image.png

当server接受到一个block块时。会尝试merge这个文件,在merge前会检索信息,通过这些原信息来正确处理一些潜在的问题和场景。

image.png

Magnet可靠性

image.png

Cloud Shuffle Service思想

image.png

Cloud Shuffle Service架构

image.png

Cloud Shuffle Service 读写流程

image.png

Cloud Shuffle Service 支持AQE

image.png

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

总结:

  • 1.学习了MapReduce和shuffle基础
  • 2.学习了shuffle算子以及构造方法,学习了shuffle的流程以及写数据和读数据
  • 3.学习了shuffle的优化以及具体的优化方法Magnet和Cloud Shuffle Service

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

网址:juejin.cn/