源码解析Spark各个ShuffleWriter的实现机制(一)——Shuffle Writer的选择

概述

什么是Shuffle?

在讲到Spark Shuffle实现机制之前,需要了解下什么是Shuffle。Shuffle按字面意思,也就是洗牌,把牌视作数据,那么洗的过程也就是按照某种规则改变数据的次序,接着发牌员发牌给玩家,发牌的过程就对应着通过网络I/O分发数据,接着玩家读牌。Shuffle正好对应了这三个过程。
假设在一场牌局中,有一位发牌员和两位玩家。一般情况下,发牌员在开始游戏之前,需要将牌随机打乱,再按序发给两位玩家,接着两位玩家开始处理牌。发牌员洗牌、发牌、玩家拿牌这三个过程中,洗牌和拿牌在Spark中分别对应Shuffle Write, Shuffle Read,文章关注的则是Shuffle Write。

Shuffle发生在哪些实例上?

在Spark中,driver是负责切分task并序列化task,协调资源,并调度派发到executor上,driver不负责处理数据,具体数据处理是由executor完成的,也就是说Shuffle是发生在executor上的。回到上边的牌局,这时候executor兼具发牌员和玩家两个职能,一般大家和朋友打扑克,总不能有人专门洗牌发牌但不玩吧~在Spark中稍复杂些,并不是一个executor在Shuffle Write,而是每个executor都在做,直到所有executor都完成了Shuffle Write,都通知driver已完成,才会进入到下一个Stage,进行Shuffle Read。

为什么需要Shuffle?

在数据量小时,一般一个单体进程即可完成加工处理,但面对海量数据处理,一台单体进程是难以胜任的。随着互联网发展,许多分布式计算框架被提出,这些框架总的来说,都是在多个分布式进程中处理不同的数据。在对数据处理过程中,时常需要:

  • group, join数据:比如根据相同key聚类,每个分布式数据处理进程处理后,将特定key的数据发往特定的分布式进程上进行聚类;
  • 数据倾斜时重分布:数据倾斜在少数分布式进程,导致其他进程空跑等待,既是浪费资源,也会影响整体处理效率,因此需要将数据发往其他分布式进程进行处理。

这两种场景就涉及到如何“洗牌”,将数据按某种规则分布到其他进程中。在Spark中有哪些操作会触发到Shuffle呢?

有哪些对RDD/DF的操作会触发到Shuffle呢?

主要是这四类:

  • .*ByKey: groupByKey, countByKey, reduceByKey等聚类算法
  • .*By: distributeBy, clusterBy等聚类算法
  • repartition: round robin重分布数据
  • join: 可能触发,当需要连接的数据广播到各个executor时,就不会触发shuffle,直接在内存中进行join

Spark中对Shuffle实现的演进历史

这部分我倒是没有细看,我开始接触时Spark就已经迭代到3.2的版本了,只是了解到在2.0之前,Shuffle的实现变化很多,主要是为了解决非功能问题,有兴趣可以了解一下,对解决日常非功能问题也有一定启发。在2.0及之后版本,Shuffle Write的实现就已经稳定了,只有以下三种:

  • UnsafeShuffleWriter: 对序列化数据直接排序(对partitionId排序),减少反序列化后排序再序列化的开销,每个分区一个FileSegment,最终所有的FileSegment合并到一份文件中。
  • BypassMergeSortShuffleWriter: bypass通过,数据怎样来就怎样写,当然会按parititionId写到不同的FileSegment中,最终所有的FileSegment会整合到同个文件中。
  • SortShuffleWriter: 对数据进行mapSideCombine(可选的),启用后可选对特定key进行聚合和排序(先排partitionId,再排key);如果不启用,只会对partitionId排序。它没有按照一个分区一个FileSegment的方式,而是在将数据插入到排序器的过程中达到一定阈值,触发排序并写入文件,再回到将数据插入排序器的过程,直至没有数据了,最终合并所有文件和可能排序器中残留的数据到一份文件。

那么Spark是如何决定使用哪种实现的呢?

使用各个Shuffle Writer的条件

源码分析

在Spark driver构建RDD之间的血缘依赖时,便根据以下条件选择构建具体的Shuffle依赖:

 // SortShuffleManager
 override def registerShuffle[K, V, C](
     shuffleId: Int,
     dependency: ShuffleDependency[K, V, C]): ShuffleHandle = {
   
   if (SortShuffleWriter.shouldBypassMergeSort
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值