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

142 阅读5分钟

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

1. 大数据处理引擎Spark介绍

Apache Spark 是一个多语言引擎,用于在单节点机器或集群上执行数据工程、数据科学和机器学习。

1.1 Spark生态和特点

  • 统一引擎,支持多种分布式场景
  • 多语言支持
  • 可读写丰富数据源
  • 丰富灵活的API算子
    • SparkCore→RDD
    • SparkSQL→DataFrame
  • 支持K8S/YARN/Mesos资源调度

2. Spark原理解析

image.png

2.1 SparkCore

用户选择了集群提交到外部资源管理器,比如说提交到YARN,在mode management创建一个appmaster,用来管理资源,是否有资源创建executor,APPmaster在YARN模式下相当于Driver也会通过DAG,Task Scheduler管理和分配Task。

Spark的数据输入到输出所有的数据结构都是基于RDD的,接下来从RDD开始说。

2.2 什么是RDD

image.png

RDD是一个可以容错的,并行执行的分布式数据集,最基本的数据处理模型。

  • 分区列表,每一个RDD都有多个分区,这些分区运行在集群不同节点上,每个分区都会被一个计算任务Task处理,分区决定了并行计算的数量。创建RDD可以指定分区个数,从集群创建的话,默认分区数是CPU核数;从HDFS文件存储创建的话,Partition个数就是文件的blog数。
  • 都有一个计算函数,RDD以Partition为基本单位,每个RDD实现一个compute函数,对具体的RDD进行计算
  • 有依赖,每一个RDD都会依赖于RDD,每次转换都会生成新的RDD,RDD会形成像Pipeline形成前后依赖关系。部分分区数据丢失时,Spark可以通过依赖关系重新计算分区数据,而不是对所有的RDD都进行重新计算
  • 实现了两种类型分区函数,一个基于哈希的Hash partitioner,基于范围的 range partitioner,两种分区器。对于只有key-value的RDD,才会有分区partitioner,非key-value的RDD,partitioner的值是空的。Partitioner不但决定了RDD本身的分区数量,也决定了parent RDD shuffle时的shuffle分区数量。
  • 每个分区有一个优先的位置列表,他会存储每个partition的优先位置,例如HDFS的文件会存储每个partition块的数据,移动数据不如移动计算,进行任务调度的时候,尽可能将计算分配到需要处理的任务块的位置。

提供了各种各样的算子,就是成员函数,map,filter返回新的RDD;count返回新的数据类型。cache,persist(缓存)当一个RDD被多次使用,这个RDD计算链路非常长,那么计算结果就会非常珍贵。可以中间进行缓存,保存计算结果,这也是Spark速度快的原因,可以在内存中持久化缓存数据集。

2.3 内存管理

image.png Spark 作为一个基于内存的分布式计算引擎,Spark采用统一内存管理机制。重点在于动态占用机制。

  • 设定基本的存储内存(Storage)和执行内存(Execution)区域,该设定确定了双方各自拥有的空间的范围,UnifiedMemoryManager统一管理Storage/Execution内存
  • 双方的空间都不足时,则存储到硬盘;若己方空间不足而对方空余时,可借用对方的空间
  • 当Storage空闲,Execution可以借用Storage的内存使用,可以减少spill等操作, Execution内存不能被Storage驱逐。Execution内存的空间被Storage内存占用后,可让对方将占用的部分转存到硬盘,然后"归还"借用的空间
  • 当Execution空闲,Storage可以借用Execution内存使用,当Execution需要内存时,可以驱逐被Storage借用的内存,可让对方将占用的部分转存到硬盘,然后"归还"借用的空间

3. SparkSQL原理解析

3.1 Catalyst优化器- RBO

  • transformDown先序遍历树进行规则匹配
  • transformUp后序遍历树进行规则匹配

3.2 Adaptive Query Execution(AQE)

每个Task结束会发送MapStatus信息给Driver

Task的MapStatus中包含当前Task Shuffle产生的每个Partition的size统计信息 Driver获取到执行完的Stages的MapStatus信息之后,按照MapStatus中partition大小信息识别匹配些优化场景,然后对后续未执行的Plan进行优化

目前支持的优化场景

  • Partiton合并,优化shuffle读取, 减少reduce task个数
  • SMJ -> BHJ
  • Skew Join优化

4. 业界挑战与实践

4.1 Shuffle稳定问题

在大规模作业下,存在本地磁盘上,没有备份,有大量的请求,数量级很大,有热点数据反复读,spill数据会带来写放大,reduce高并发读取小数据块会带来磁盘随机访问的问题,也是低效率的问题,NodeManager的模块也会经常JC。解决方案:

  • 数据远端存储
  • 在partition端shuffle的时候进行聚合,少了很多排序的操作

4.2 SQL执行性能问题

向量法/Codegen/两者结合、C++/Java

4.3 参数推荐/作业诊断

Spark参数很多,参数不合理的作业,对资源利用率/Shuffle稳定性/性能有非常大影响。 自动化参数推荐/作业诊断——自动化

总结

这节课上我学到了:

  1. 大数据处理常见的场景链路
  2. Spark技术栈,包括SparkCore中的RDD/调度/Shuffle/内存管理等概念机制,以及SQL在Spark引擎中执行的详细流程
  3. 目前业界主要遇到的挑战以及解决方案

参考

  1. 【大数据专场 学习资料二】第四届字节跳动青训营 - 掘金 (juejin.cn)
  2. Apache Spark™ - Unified Engine for large-scale data analytics
  3. Spark Shuffle原理和Shuffle的问题解决和优化_水墨风漾的博客-CSDN博客