Spark原理与实践|青训营笔记

132 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第5天

  • Spark介绍
    • 基于内存计算的大数据开源计算集群环境
    • 特点
      • 统一引擎,支持多种分布式场景
      • 多语言支持
      • 可读写丰富数据源
      • 丰富灵活的API算子
        • SparkCore->RDD
        • SparkSQL->DataFrame
      • 支持K8S/YARN/Mesos资源调度
        • 部署方式
          • Spark Local Mode
            • 本地测试/单进程多线程模式
          • Spark Standalone Mode
            • 需要启动SparkStandalone集群的master/worker
          • on YARN/K8S
            • 依赖外部资源调度器(YARN/K8S)
  • SparkCore原理解析
    • RDD(Resilient Distributed Dataset)
      • 是一种对数据集形态的抽象,基于此抽象,使用者可以在集群中执行一系列计算,而不用将中间结果落盘。
      • 五要素
        • Partitions(分区集)
          • 分区是每个RDD最小构成单元
        • Compute(变换函数)
          • 作用于分区上的变换函数,可以由几个父分区计算得到一个子分区
        • Dependencies(依赖集)
          • RDD之间存在父子依赖关系
        • Partitioner(分区模式)
          • 基于哈希切片/直接切分
        • PreferredLocations(数据放置)
          • 知道分区的存放位置可以进行计算优化
      • 如何创建RDD
        • 内置RDD
          • ShuffleRDD/HadoopRDD/JDBCRDD
          • KafkaRDD/UnionRDD/MapPartitionsRDD
        • 自定义RDD
          • class CustomRDD(...)extends RDD{}
          • 实现五要素对应的函数
      • RDD算子
        • Transform算子
          • 生成一个新的RDD
          • map/filter/flatMap/groupBy/reduceBy
        • Action算子
          • 触发Job提交
          • collect/count/take/saveAsTextFile
      • RDD依赖
        • 窄依赖
          • RDD的每个partition至多对应一个子RDD分区
          • NarrowDependency
          • OneToOneDependency
          • RangeDependency
          • PruneDependency
        • 宽依赖
          • RDD的每个partition可能对应多个子RDD分区
          • ShuffleDependency
      • 调度器
        • RDD.action->runJob()
        • 根据ShuffleDependency切分stage,并按照依赖顺序调度stage,为每个stage生成并提交TaskSetTaskScheduler
        • 根据调度算法(FIFO/FAIR)对多个TaskSet进行调度,对于调度到的TaskSet,会将Task调度(locality)到相关Executor上执行,Executor SchedulerBackend提供
      • 内存管理
        • Executor内存主要有两类:Storage/Execution
        • UnifiedMemoryManager统一管理Storage/Execution内存
        • Storage/Execution内存使用动态调整,可以相互借用
        • Storage空闲时,Execution可以借用Storage的内存使用
          • 可以减少spill等操作,Execution使用的内存不能被Storage驱逐
        • Execution空闲时,Storage可以借用Execution的内存使用
          • Execution需要内存时,可以驱逐被Storage借用的内存,直到spark.memory.storageFraction边界
      • 多任务间内存分配
        • UnifiedMemoryManager统一管理多个并发Task的内存分配
        • 每个Task获取的内存区间为1/(a*N)~1/N(N为当前Executor中正在并发运行的Task数量)
      • Shuffle机制
        • mapreduce之间数据处理和重新分发的过程被称为Shuffle
        • SortShuffleManager
        • External Shuffle Service
  • SparkSQL原理解析
    • Catalyst优化器*
      • RBO
        • RuleExecutor
          • Batch->Once
            • 只执行一次
          • Batch->FixedPoint
            • 重复执行,直到plan不在变化,或者执行达到固定次数(默认100次)
      • CBO
    • AQE(Adaptive Query Execution)
      • partition合并
        • 作业运行过程中,根据前面运行完的StageMapStatus中实际的partition大小信息,可以将多个相邻的较小的partition进行动态合并,由一个task读取进行处理
      • 动态切换join策略
        • AQE运行过程中动态获取准确joinleftchild/rightChild的实际大小,将SMJ转换为BHJ
      • 处理join倾斜问题
        • AQE根据MapStatus信息自动检测是否有倾斜,将大的partition拆分成多个task进行join
    • Runtime Filter
    • Bloom Runtime Filter
    • Codegen
      • Expression
        • 将表达式中的大量虚函数调用压平到一个函数内部,类似手写代码
      • WholeStageCodegen
        • 算子之间大量虚函数调用,开销大,将同一个stage的多个算子压平到一个函数内部使用
  • 业界挑战与实践
    • Shuffle稳定性问题
      • 在大规模作业下,开源ESS(ExternalShuffleService)的实现机制容易带来大量随机读导致的磁盘IOPS瓶颈、Fetch请求积压等问题,进而导致运算过程中经常会出现Stage重算甚至作业失败,继而引起资源使用的恶性循环,严重影响SLA
    • SQL执行性能问题
    • 参数推荐/作业诊断