spark的shuffle过程

(1)shuffle的概述

  Shuffle描述着数据从map task输出到reduce task输入的这段过程。因为是分布式存储,reduce task需要跨节点去拉取其它节点上的map task结果。这一过程将会产生网络资源消耗和内存,磁盘IO的消耗。通常shuffle分为两部分:Map阶段的数据准备和Reduce阶段的数据拷贝处理。

(2)hash shuffle

  1、普通运行机制

       

    1)运行流程

     a、每一个shuffleMapTask将不同结果写到不同的buffer中,每个buffer的大小为32K。buffer起到数据缓存的作用。当内存缓冲填满之后,才会溢写到磁盘文件中去。

     b、每一个bucket创建一个block file文件。这个bucket存放的数据就是经过Partitioner操作(默认是HashPartitioner)之后找到对应的bucket然后放进去。

     c、resultTask来拉取对应的磁盘小文件。一边拉取一边进行聚合的。每个resultTask都会有一个自己的buffer缓冲,每次都只能拉取与buffer缓冲相同大小的数据,然后通过内存中的一个Reduce进行操作。

    2)注意事项

     a、buffer起到的是缓存作用,缓存能够加速写磁盘,提高计算的效率;分区器:根据hash/numRedcue取模决定数据由几个Reduce处理,也决定了写入几个buffer中

     b、产生的磁盘小文件的个数:M(shuffleMapTask的个数)* R(resultTask的个数)

    3)缺点

     a、Shuffle前在磁盘上会产生海量的小文件,建立通信和拉取数据的次数变多,此时会产生大量耗时低效的 IO 操作 (因為产生过多的小文件)

     b、可能导致OOM,大量耗时低效的 IO 操作 ,导致写磁盘时的对象过多,读磁盘时候的对象也过多,这些对象存储在堆内存中,会导致堆内存不足,相应会导致频繁的GC,GC会导致OOM。由于内存中需要保存海量文件操作句柄和临时信息,如果数据处理的规模比较庞大的话,内存不可承受,会出现 OOM 等问题。

  2、合并机制的Hash shuffle

       

   1)一个Executor上有多少个CPU core,就可以并行执行多少个task。而第一批并行执行的每个task都会创建一个shuffleFileGroup,并将数据写入对应的磁盘文件内。Executor的CPU core执行完一批task,接着执行下一批task时,下一批task就会复用之前已有的shuffleFileGroup,包括其中的磁盘文件。也就是说,此时task会将数据写入已有的磁盘文件中,而不会写入新的磁盘文件中。consolidate机制允许不同的task复用同一批磁盘文件,这样就可以有效将多个task的磁盘文件进行一定程度上的合并,从而大幅度减少磁盘文件的数量,进而提升shuffle write的性能。

   2)产生小文件的个数:block file=Core*R,Core为CPU的核数,R为Reduce的数量

   3)缺点:如果 Reducer 端的并行任务或者是数据分片过多的话则 Core * Reducer Task 依旧过大,也会产生很多小文件。

(3)sort shuffle

  SortShuffle的运行机制主要分成两种,一种是普通运行机制,另一种是bypass运行机制。当shuffle map task的数量小于等于spark.shuffle.sort.bypassMergeThreshold参数的值时(默认为200),就会启用bypass机制。

  1、普通执行机制

     

 

   数据会先写入一个内存数据结构中(默认5M),此时根据不同的shuffle算子,可能选用不同的数据结构。如果是reduceByKey这种聚合类的shuffle算子,那么会选用Map数据结构,一边通过Map进行聚合,一边写入内存;如果是join这种普通的shuffle算子,那么会选用Array数据结构,直接写入内存。接着,每写一条数据进入内存数据结构之后,就会判断一下,是否达到了某个临界阈值。如果达到临界阈值的话,那么就会尝试将内存数据结构中的数据溢写到磁盘,然后清空内存数据结构。

   1)执行流程

    a、shuffle map task 的计算结果会写入到一个内存数据结构里面,内存数据结构默认是5M

    b、在shuffle的时候会有一个定时器,不定期的去估算这个内存结构的大小,当内存结构中的数据超过5M时,比如现在内存结构中的数据为5.01M,那么他会申请5.01*2-5=5.02M内存给内存数据结构。即:applyMemory=nowMenory*2-oldMemory

    c、 如果申请成功不会进行溢写,如果申请不成功,这时候会发生溢写磁盘。

    d、在溢写之前内存结构中的数据会进行排序分区

    e、然后开始溢写磁盘,写磁盘是以batch的形式去写,一个batch是1万条数据,

    f、map task执行完成后,会将这些磁盘小文件合并成一个大的磁盘文件,同时生成一个索引文件。

    g、result task去map端拉取数据的时候,首先解析索引文件,根据索引文件再去拉取对应的数据。

   2)总结

    a、block file= 2M,一个shuffle map task会产生一个索引文件和一个数据大文件

  2、byPass机制

     

   1)触发条件

    a、shuffle map task数量小于spark.shuffle.sort.bypassMergeThreshold参数的值。

    b、不是聚合类的shuffle算子(比如reduceByKey)。

   2)执行流程

    a、task会为每个reduce端的task都创建一个临时的内存缓冲和磁盘文件,并将数据按key进行hash然后根据key的hash值将key写入对应的内存缓冲之中

    b、内存缓冲写满之后再溢写到磁盘文件,会将所有临时磁盘文件都合并成一个磁盘文件,并创建一个单独的索引文件。

   3)与sort shuffle的相比:不会进行排序,没有内存结构缓存数据,启用该机制的最大好处在于,shuffle write过程中,不需要进行数据的排序操作,也就节省掉了这部分的性能开销。

 

posted on 2020-05-07 16:30  hdc520  阅读(1072)  评论(0编辑  收藏  举报

导航