Spark核心概念与宽窄依赖的详细解析
Spark核心概念与宽窄依赖的详细解析
Apache Spark作为大数据处理领域的主流框架,其复杂的架构和运行机制常常让初学者望而却步。本文将深入剖析Spark中的关键概念,包括ClusterManager、Worker、Application、Driver、Executor、Job、Stage、Task等,并详细讲解Spark应用的提交流程,以及宽窄依赖这一重要特性,旨在帮助读者全面理解Spark的工作原理,为进一步深入学习和应用Spark打下坚实基础。
一、Spark核心概念解析
(一)架构层面概念
ClusterManager(统称)
分布式资源管理平台的主节点。在Standalone模式下是Master,在YARN模式下是ResourceManager。
主要功能包括管理从节点、接受客户端请求、进行资源管理和任务调度。它就像是整个分布式系统的指挥官,掌控着资源的分配和任务的派发大权。
Worker(统称)
分布式资源管理平台的从节点。对应Standalone模式下的Worker和YARN模式下的NodeManager。
其职责是利用自身节点的资源去运行主节点分配的计算进程,是具体执行任务的“士兵”,为整个分布式计算提供计算力支持。
(二)程序层面概念
Application
即Spark的应用程序,是开发者基于Spark的API开发的程序。在集群模式中,任何一个Spark程序都会包含一个Driver进程和多个Executor进程,而在单机模式下只有一个Driver。可以在4040界面查看相关信息。
Driver
Spark程序的驱动进程,类似于项目中的项目经理。它先启动,会调用SparkContext来实现自身功能,主要负责申请资源启动Executor进程,解析代码构建Task、调度分配Task、监控Task运行等一系列关键操作,是整个Spark应用程序的核心驱动力量。
Executor
Spark程序的执行进程,是计算进程。后启动且运行在从节点中,使用从节点的CPU和内存(可通过参数如--executor-mem和--executor-cores进行配置)。其主要功能是负责运行Driver分配的Task分区,每个Task使用1CoreCPU来运行,并且可以将Task的数据缓存在内存中,是实际执行计算任务的单元。
(三)运行层面概念
Job
是Spark触发计算的最小单元。由Driver解析代码,遇到触发算子时就会构建job。一个代码可以有多个触发算子,所以一个Spark程序可以包含多个job。当Job被触发后,Driver会调用DAGScheduler组件为其构建DAG图(执行计划)。
Stage
是Spark转换Task的最小单元。由DAGScheduler根据回溯算法构建整个Job的DAG图,在构建过程中会按照Shuffle过程(宽依赖)划分Stage。每个Stage内部都是由Task直接在内存中转换完成,不同Stage之间需要经过磁盘来完成。根据数据处理过程,每一个Shuffle过程,就要构建一个 新的Stage,一个job中有N个Shuffle,就会产生N+1个Stage。
Task
是Spark执行计算的最小单元。一个Job由多个Stage构成,每个Stage都会转换成为一个TaskSet(Task集合),每个TaskSet中可以包含多个Task。Task的个数由Stage中最后一个RDD的分区数或者最小的RDD分区数来决定(Spark为避免资源浪费,选择用最少Task来完成)。最终job的所有Task都会由Driver按照优先本地计算的原则分配给不同的Executor去运行。
(四)Stage转换的TaskSet中Task个数由什么决定?
每个Stage会转换成一个TaskSet集合
TaskSet集合中Task的个数由这个Stage中最后一个RDD的分区数 或者 最小的RDD分区数来决定
Spark为了避免资源浪费,导致一部分Task工作,另一部分不工作,所以选择用最少Task来完成
(五)降低分区可以不经过shuffle就实现,为什么有时候建议走Shuffle来降低分区?
repartiton算子: 一般用于扩大分区数,底层调用的还是coalesce,是否经过shuffle写死了是True
coalesce算子:一般用于减少分区数,默认shuffle= False ,所以只用于减少分区,想扩大,手动shuffle= True
记住结论:
规则:调整分区个数,如果RDD的分区由N调整到M
N < M:增大分区:必须经过Shuffle才能实现
N > M:降低分区:可以经过Shuffle,也可以不经过
N远大于M:建议经过Shuffle来实现,N=1000, M=10
N和M差距不大:建议不经过Shuffle来实现,N=100, M=80
比例:超过10:1,建议走Shuffle
(六)在 spark 中什么模式下能访问 4040 界面?什么情况下能访问 8080 界面?
单机版:可以看见4040
standalone 版:4040 和 8080 也都可以看见。
Yarn 版:只启动了 yarn,spark 任何程序都没有启动,所以 4040 和 8080 页面都访问不了,可以在 yarn 上查看,端口是 8088。
二、Spark 应用提交流程
spark任务提交执行流程图:(deploy-mode = client模式)
(一)前提准备
先启动分布式资源管理的集群,如Spark Standalone或YARN。
(二)提交步骤
- 客户端提交用户开发好的Spark Application程序给ClusterManager。
- ClusterManager根据配置参数运行程序,启动Driver进程。
- Driver进程向主节点提交申请启动Executor进程。
- 主节点根据资源配置和请求,在从节点上启动Executor进程。
- 所有Executor启动成功以后,会向Driver反向注册,等待分配Task。
- Driver解析代码,直到遇到触发算子,开始触发job的运行。
- Driver会调用DAGScheduler组件为当前这个job通过回溯算法构建DAG图,并划分Stage。
- Driver会将这个job中每个Stage转换为TaskSet,根据Stage中最后一个RDD分区数来构建Task个数。
- Driver调用TaskScheduler将Task调度分配到Executor中运行。
三、Spark 中的宽窄依赖
(一)依赖关系概述
在Spark中,RDD之间存在着依赖关系,这种依赖关系对于数据处理和任务调度有着重要的影响。
(二)宽窄依赖定义与特点
本质:只是一种标记,标记两个RDD之间的依赖关系
窄依赖(Narrow Dependencies)
定义:父RDD的一个分区的数据只给了子RDD的一个分区,无需经过Shuffle。
特点:一对一或者多对一的关系,不经过Shuffle,性能相对较快,但无法实现全局分区、排序、分组等操作。一个Stage内部的计算都是窄依赖的过程,全部在内存中完成。例如,map、filter等算子产生的就是窄依赖。
宽依赖(Wide/Shuffle Dependencies)
定义:父RDD的一个分区的数据给了子RDD的多个分区,需要调用Shuffle的分区器来实现。
特点:一对多的关系,必须经过Shuffle,性能相对较慢,但可以实现全局分区、排序、分组等操作。Spark的job中按照宽依赖来划分Stage。例如,reduceByKey等涉及数据重分区的算子产生的就是宽依赖。
(三)标记宽窄依赖的意义
提高数据容错性能
当子RDD的某个分区的数据丢失时,如果没有标记宽窄依赖,不清楚父RDD与子RDD数据之间的关系,必须重新构建整个父RDD所有数据。而标记了宽窄依赖后,父RDD一个分区只对应子RDD的一个分区,按照对应关系恢复父RDD的对应分区即可,大大减少了数据恢复的工作量和资源消耗。
提高数据转换性能
对于多个算子的转换操作,如果不标记宽窄依赖,每个转换不知道会不会经过Shuffle,都使用不同的Task来完成,每个Task的结果要保存到磁盘。而标记了宽窄依赖后,多个连续窄依赖算子放在一个Stage中,共用一套Task在内存中完成所有转换,避免了不必要的磁盘读写,提高了性能。
四、总结
通过对Spark中的ClusterManager、Worker、Application、Driver、Executor、Job、Stage、Task等核心概念的详细解析,以及对Spark应用提交流程和宽窄依赖特性的深入探讨,我们可以看到Spark构建了一个复杂而高效的分布式计算框架。理解这些概念和机制对于正确使用Spark进行大数据处理至关重要。无论是开发大规模数据处理应用,还是深入研究Spark的内部原理,都需要牢牢掌握这些知识要点。希望本文能够为读者在Spark的学习和应用之路上提供有益的参考和指引,让大家能够更加从容地驾驭Spark这一强大的大数据处理工具。