Spark的Shuffle过程解释

初始RDD分区个数由Split个数决定(老师说若读取HDFS初始也参考spark.default.parallelism参数指定分区数,如果使用SparkSQL读取Hive或者MySQL数据,初始按照split个数,不参考该参数),假定为N。执行过程中假如没有执行重分区则分区个数还是N,如果执行到Shuffle,Shuffle分为Map端和Reduce端,Map端的任务个数还是N,Reduce端(下个Stage)默认取spark.default.parallelism的值作为分区数,如果该值未配置,则和上一个Shuffle最末端(Map端)的任务个数一致。Shuffle的Map端结束会将数据溢写到磁盘(猜测非HDFS,先内存)并把该位置告知Driver(MapOutputTrackerWorker对象将mapStatus发给Driver的MapOutputTrackerMaster对象),下个Stage阶段Reduce端Task的MapOutputTrackerWorker向Driver的MapoutputTrackerMaster获取数据位置,然后有BlockTransferService去指定的Executor拉取数据放入20%的Executor内存中,默认启动5个子线程,每次拉取不超过48MB。任务在执行时从指定位置拉取数据(例如知道HDFS具体的Block了吧?)。

Shuffle的Map端写入:假设reduce分区个数为M,将写入M个文件,未经优化的HashShuffleManager每个Map任务都写入M个文件,将产生大量的小文件,优化后的每个CPU核心写入M个文件,下次再有Task写入直接复用原来的文件。现在优化和未优化的HashShuffleManager已经淘汰了。现在使用SortShuffleManager,包括两种运行机制,第一是普通运行机制,内存中数据达到阈值后,取10000条进行排序然后通过Java的BufferedOutputStream(自动内存缓存,优化IO性能)写入到单独的文件,写入完成之后所有的文件合并成一个大文件和一个索引文件(对应Partition的索引?),这里不针对Reduce端任务数分文件了。在Map端还会针对reduceByKey、join算子进行Map端的处理;第二种是Bypass方式,当Map端的任务数量小于spark.shuffle.sort.bypassMergeThreshold参数值时启用,写入时也会根据Hash产生M个文件,写入方式先写入缓存,然后溢写到磁盘文件,这个过程和未经优化的HashShuffleManager基本一模一样,不同之处是最后会合并成一个文件和索引文件。

SparkShuffle过程是指在数据处理过程中,将数据重新分区和排序的过程。它是Spark中非常重要的一个操作,用于将数据从一个RDD的分区传输到另一个RDD的分区。 SparkShuffle过程包括两个阶段:Map阶段和Reduce阶段。 在Map阶段,每个Executor上的任务(Task)会将输入数据根据指定的分区函数进行分区,并将分区后的数据写入磁盘上的.data文件中。同时,还会生成一个.index文件,用于记录每个分区的数据在.data文件中的位置信息。 在Reduce阶段,Spark会根据分区函数将数据重新分配到不同的Executor上的任务中。每个任务会读取自己负责的分区数据,并进行合并、排序等操作,最终生成最终结果。 SparkShuffle过程可以使用不同的策略来实现,其中包括BypassMergeSortShuffleWriter、SortShuffleWriter和UnsafeSortShuffleWriter等。 BypassMergeSortShuffleWriter是一种优化策略,它会尽量减少数据的复制和排序操作,提高Shuffle的性能。 SortShuffleWriter是一种常用的策略,它会将数据写入磁盘,并使用外部排序算法对数据进行排序。 UnsafeSortShuffleWriter是一种更高效的策略,它使用了内存进行排序,减少了磁盘IO的开销。 下面是一个示例代码,演示了SparkShuffle过程: ```scala val inputRDD = sc.parallelize(List(("apple", 1), ("banana", 2), ("apple", 3), ("banana", 4))) val shuffledRDD = inputRDD.groupByKey() val resultRDD = shuffledRDD.mapValues(_.sum()) resultRDD.collect().foreach(println) ``` 这段代码首先创建了一个输入RDD,其中包含了一些键值对数据。然后使用groupByKey()函数对数据进行分组,生成一个ShuffledRDD。最后使用mapValues()函数对每个分组进行求和操作,得到最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值