• spark 笔记2


     

    一、Spark Shuffle 的发展

    • Spark 0.8及以前 Hash Based Shuffle
    • Spark 0.8.1 为Hash Based Shuffle引入File Consolidation机制
    • Spark 0.9 引入ExternalAppendOnlyMap
    • Spark 1.1 引入Sort Based Shuffle,但默认仍为Hash Based Shuffle
    • Spark 1.2 默认的Shuffle方式改为Sort Based Shuffle
    • Spark 1.4 引入Tungsten-Sort Based Shuffle
    • Spark 1.6 Tungsten-sort并入Sort Based Shuffle
    • Spark 2.0 Hash Based Shuffle退出历史舞台
     
     
    Spark Shuffle 机制总共有三种:

    1. 未优化的 HashShuffle
    2. 优化后 HashShuffle (引入了 Consolidation 机制)
    3. Sort-Based Shuffle

    由于 HashShuffle 会产生很多的磁盘文件,引入 Consolidation 机制虽然在一定程度少了磁盘文件数量,但是不足以有效提高 Shuffle 的性能,适合中小型数据规模的大数据处理。

    Spark 2.3中,唯一的支持方式为 SortShuffleManagerSortShuffleManager 中定义了 writer reader 对应shuffle map reduce 阶段。reader 只有一种实现 BlockStoreShuffleReaderwriter 有三种运行实现:

    • BypassMergeSortShuffleWriter:当前 shuffle 没有聚合,并且分区数小于 spark.shuffle.sort.bypassMergeThreshold(默认200
    • UnsafeShuffleWriter:当条件不满足 BypassMergeSortShuffleWriter 时, 并且当前 rdd 的数据支持序列化(即 UnsafeRowSerializer),也不需要聚合, 分区数小于 2^24
    • SortShuffleWriter:其余所有shufle

    特点: 

    BypassMergeSortShuffle

      1. 算法适用于没有聚合,数据量不大的场景, BypassMergeSortShuffleWriter 所有的中间数据都是在磁盘里,并没有利用内存。而且它只保证分区索引的排序,而并不保证数据的排序

      2. 和Hash Shuffle中的HashShuffleWriter实现基本一致, 唯一的区别在于,map端的多个输出文件会被汇总为一个文件。 所有分区的数据会合并为同一个文件,会生成一个索引文件,是为了索引到每个分区的起始地址,可以随机 access 某个partition的所有数据

    SortShuffleWriter  

      1. 会有不同的数据结构: PartitionedAppendOnlyMap(需要内部聚合), PartitionedPairBuffer 不需要内部聚合

      2.处理步骤:   

    1. 使用 PartitionedAppendOnlyMap 或者 PartitionedPairBuffer 在内存中进行排序,  排序的 K 是(partitionId, hash(key)) 这样一个元组。
    
    2. 如果超过内存 limit, 我 spill 到一个文件中,这个文件中元素也是有序的,首先是按照 partitionId的排序,如果 partitionId 相同, 再根据 hash(key)进行比较排序
    
    3. 如果需要输出全局有序的文件的时候,就需要对之前所有的输出文件 和 当前内存中的数据结构中的数据进行  merge sort, 进行全局排序

    UnsafeShuffleWriter

      1. 触发条件:Serializer 支持 relocation, 

      2. 没有指定 aggregation 或者 key 排序,

      3. partition 数量不能大于指定的阈值(2^24),因为 partition number 使用24bit 表示的

      4. 特点: 原始数据首先被序列化处理,并且再也不需要反序列,在其对应的元数据被排序后,需要Serializer支持relocation,在指定位置读取对应数据

     

    小结:

    下图是相关的uml图

    ShuffleHandle类 会保存shuffle writer算法需要的信息。根据ShuffleHandle的类型,来选择ShuffleWriter的类型。

    ShuffleWriter负责在map端生成中间数据,ShuffleReader负责在reduce端读取和整合中间数据。

    ShuffleManager 提供了registerShuffle方法,根据shuffle的dependency情况,选择出哪种ShuffleHandler。它对于不同的ShuffleHandler,有着不同的条件

    • BypassMergeSortShuffleHandle : 该shuffle不需要聚合,并且reduce端的分区数目小于配置项spark.shuffle.sort.bypassMergeThreshold,默认为200
    • SerializedShuffleHandle : 该shuffle不需要聚合,并且必须支持序列化时seek位置,还需要reduce端的分区数目小于16777216(1 << 24 + 1)
    • BaseShuffleHandle : 其余情况

    getWriter方法会根据registerShuffle方法返回的ShuffleHandler,选择出哪种 shuffle writer,原理比较简单:

    • 如果是BypassMergeSortShuffleHandle, 则选择BypassMergeSortShuffleWriter

    • 如果是SerializedShuffleHandle, 则选择UnsafeShuffleWriter

    • 如果是BaseShuffleHandle, 则选择SortShuffleWriter

    ShuffleWriter只有两个方法,write和stop方法。使用者首先调用write方法,添加数据,完成排序,最后调用stop方法,返回MapStatus结果。下面依次介绍ShuffleWriter的三个子类。


    Spark MapOutputTracker 原理

    Spark的shuffle过程分为writer和reader两块。 writer负责生成中间数据,reader负责整合中间数据。而中间数据的元信息,则由MapOutputTracker负责管理。 它负责writer和reader的沟通。

    shuffle writer会将中间数据保存到Block里面,然后将数据的位置发送给MapOutputTracker。

    shuffle reader通过向 MapOutputTracker获取中间数据的位置之后,才能读取到数据。

    参考引用:

    https://zhmin.github.io/2019/01/26/spark-shuffle-writer/ 

     

  • 相关阅读:
    A/B-test
    LDA概率主题模型
    减肥经验帖
    wide and deep
    利用责任链模式设计一个拦截器
    分享几个 SpringBoot 实用的小技巧
    「造个轮子」——cicada 设计一个配置模块
    「造个轮子」——cicada 源码分析
    「造个轮子」——cicada(轻量级 WEB 框架)
    强如 Disruptor 也发生内存溢出?
  • 原文地址:https://www.cnblogs.com/snow-man/p/13362263.html
Copyright © 2020-2023  润新知