1、宽依赖和窄依赖

cluster spark 依赖包 spark 窄依赖_数据

1、区别

窄依赖: 父rdd的一个分区只对应子rdd一个分区。
    窄依赖允许在一个集群节点上以流水线的方式(pipeline)计算所有父分区。
    算子:map、union、map join和broadcast join。

宽依赖:父rdd的一个分区只对应子rdd多个分区。
    宽依赖需要首先计算好所有父分区数据,然后在节点之间进行Shuffle。
    算子:reduceByKey,groupByKey,常用join。 

2、重要的原因
DAG:
    Spark中RDD的高效与DAG执行引擎有着莫大的关系,而在DAG调度过程中一个stage的拆分依赖的
        就是rdd间的宽窄依赖关系。
    一个stage遇到一个宽依赖就会被拆分成两个stage,后一个stage的task会从前一个stage的
        task所在节点拉取数据,这就是shuffle。
    一个stage遇到一个窄依赖,则会将窄依赖对应rdd纳入该stage进行计算。

重算:
    对于窄依赖,子rdd一个分区数据丢失只需要对一个父rdd进行重算,重算利用率100%。
    对于宽依赖,子rdd一个分区数据丢失需要多该分区依赖的所有父rdd分区进行重算,重算利用率低。  

3、并行度
    一个stage的并行度由stage的最后一个rdd的分区决定。
    可以通过spark.default.parallelism可以设置当前stage的并行度。
    提高并行度:
        shuffle类算子第二个参数。
        重分区算子。

4、数据落地
    suffle write(可能落盘)
    持久化(取决于持久化策略)

 stage拆分

cluster spark 依赖包 spark 窄依赖_cluster spark 依赖包_02

2、Spark中的shuffle

shuffle简介

1、shuffle的概念:
    shuffle是spark中数据重分发的一种机制,以便于在跨分区进行数据的分组。shuffle通常会引
 起executor与节点之间的数据复制,这期间会有大量的网络I/O,磁盘I/O和数据的序列化。这使得
 shuffle操作十分地复杂和昂贵。
    在shuffle内部,单个map tasks的结果被保存在内存中,直到放不下为止。然后,根据目标分区
 对它们进行排序,并将它们写入单个文件。在reduce端,tasks会读取相关的经过排序的数据块。
     shuffle还会在磁盘上产生大量的中间文件,这样做是为了当触发重算的时候这些中间文件不用
 被重新创建。垃圾收集可能会发生在很长的一段时间之后,如果应用程序保留了对这些RDD的引用,
 或者垃圾收集不经常启动的话。这意味着对于一个运行时长较长的spark作业,它可能会消耗大量的
 磁盘空间。这些中间文件的存储目录在配置Spark Context时由spark.local.dir参数明确指定。
    

2、shuffle算子:
    重分区算子、ByKey算子(除了countByKey)、join()算子、cogroup/partitionBy都会触发shuffle。

shuffleManager的发展

1、ShuffleManager:
    负责整个shuffle过程的管理与计算。
    Spark 1.2之前,使用HashShuffleManager。之后改为SortShuffleManager。  


2、HashShuffleManager(已经废弃):
    Spark 1.2之前,分为未优化的和优化后的两大类。
    该管理器会产生大量的中间磁盘文件,以及大量的磁盘IO操作影响了性能。
    未经优化的HashShuffleManager:
                磁盘文件=map*reduce  
    经优化的HashShuffleManager:
                只是开启一个参数。
                磁盘文件=executor*reduce
    

3、SortShuffleManager
    普通机制:
        磁盘文件:2*map  一个数据文件一个索引文件
    bypass机制:
        磁盘文件:2*map    一个数据文件一个索引文件
        bypass机制就是普通机制基础上去掉排序。
        开启条件:
            shuffle map task数量小于spark.shuffle.sort.bypassMergeThreshold参数的值。
            不是map端预聚合的shuffle算子,比如重分区算子等就不会聚合。 
             


具体介绍参考:

未经优化的HashShuffleManager

cluster spark 依赖包 spark 窄依赖_cluster spark 依赖包_03

 经过优化的HashShuffleManager

cluster spark 依赖包 spark 窄依赖_数据_04

SortShuffleManager普通机制

cluster spark 依赖包 spark 窄依赖_数据_05

SortShuffleManager的bypass机制

cluster spark 依赖包 spark 窄依赖_内存管理_06

shuffle文件寻址

cluster spark 依赖包 spark 窄依赖_cluster spark 依赖包_07

3、内存管理

cluster spark 依赖包 spark 窄依赖_spark_08

内存管理

1、静态内存管理
    20%  task运行 
    20% :      spark.shuffle.memoryFraction
        20%  预留   
        80%  shuffle聚合内存
    60% :      spark.storage.memoryFraction
        10%  预留   
        90%:
              20% 反序列化内存    spark.storage.unrollFraction
              80% rdd缓存+广播变量
问题:
   shuffle聚合内存及task运行内存太小  

2、统一内存管理
    300MB    预留
    40%      task运行
    60%:     spark.memory.fraction 
          50%  rdd缓存和广播变量  spark.memory.storageFraction 
          50%  shuffle聚合内存 
          ####这两个50%之间是可以相互借用的。


3、注意
spark 2.0之前默认的内存管理策略是静态内存管理
saprk 2.0虽然保留了静态内存管理,但默认的策略是同一内存管理