SPARK

Spark的特点包括内存计算、丰富的API、SQL支持和流处理能力。其运行流程涉及Driver、Executor和DAGScheduler的交互,DAG是基于RDD转换形成的。在YARN上,Spark可以以Client或Cluster模式运行,区别在于Driver的位置和交互方式。文章还讨论了SparkSQL、数据倾斜的解决方案、checkpoint机制以及不同类型的JOIN操作。
摘要由CSDN通过智能技术生成

spark 特点,优点

快 基于内存,
api算子多,
支持sql,流处理,机器学习
支持yarn调用
 

Spark的运行流程

上图为Spark通用运行流程图,体现了基本的Spark应用程序在部署中的基本提交流程。 这个流程是按照如下的核心步骤进行工作的: 1)任务提交后,都会先启动Driver程序;

2)随后Driver向集群管理器注册应用程序;

3)之后集群管理器根据此任务的配置文件分配Executor并启动;

4Driver开始执行main函数,Spark查询为懒执行,当执行到Action算子时开始反向推算,根据宽依赖进 Stage的划分,随后每一个Stage对应一个TasksetTaskset中有多个Task,查找可用资源Executor进行 调度;

5)根据本地化原则,Task会被分发到指定的Executor去执行,在任务执行的过程中,Executor也会不断 Driver进行通信,报告任务运行情况。

DAG的生成

DAG(Directed Acyclic Graph)叫做有向无环图,原始的RDD通过一系列的转换就就形成了DAG,根据RDD之 间的依赖关系的不同将DAG划分成不同的Stage,对于窄依赖,partition的转换处理在Stage中完成计算。 对于宽依赖,由于有ShuVle的存在,只能在parent RDD处理完成后,才能开始接下来的计算,因此宽依 赖是划分Stage的依据

窄依赖:指的是每一个父RDDPartition最多被子RDD的一个Partition使用
宽依赖:指的是多个子
RDDPartition会依赖同一个父RDDPartition

DAGScheduler 这个类的任务就是用来划分Stage任务的

Spark SQL:提供通过Apache HiveSQL变体Hive查询语言(HiveQL)与Spark进行交互的API。每个数据 库表被当做一个RDDSpark SQL查询被转换为Spark操作。

Spark  on  standalone模型、YARN架构模型(画架构图)

可回答:Spark client和cluster模式有什么区别

1Spark on Standalone运行过程(架构)

Standalone模式是Spark实现的资源调度框架,其主要的节点有Client节点、Master节点和Worker节点。 其中Driver既可以运行在Master节点上中,也可以运行在本地Client端。当用spark-shell交互式工具提交 SparkJob时,DriverMaster节点上运行;当使用spark-submit工具提交Job或者在EclipseIDEA等开发 平台上使用 new SparkConf().setMaster(“spark://master:7077”) 方式运行Spark任务时,Driver 是运行在本地Client端上的。

运行流程如下: 1)我们提交一个任务,任务就叫Application 2)初始化程序的入口SparkContext

初始化DAG Scheduler

初始化Task Scheduler

3Task Schedulermaster去进行注册并申请资源(CPU CoreMemory);

4Master根据SparkContext的资源申请要求和Worker心跳周期内报告的信息决定在哪个Worker上分配资 源,然后在该Worker上获取资源,然后启动StandaloneExecutorBackend;顺便初始化好了一个线程池;

5StandaloneExecutorBackendDriver(SparkContext)注册,这样Driver就知道哪些Executor为他进行服 务了。到这个时候其实我们的初始化过程基本完成了,我们开始执行transformation的代码,但是代码并 不会真正的运行,直到我们遇到一个action操作。生产一个job任务,进行stage的划分;

6SparkContextApplicaiton代码发送给StandaloneExecutorBackend;并且SparkContext解析 Applicaiton代码,构建DAG图,并提交给DAG Scheduler分解成Stage(当碰到Action操作时,就会催生 Job;每个Job中含有1个或多个StageStage一般在获取外部数据和shuVle之前产生);

7)将Stage(或者称为TaskSet)提交给Task SchedulerTask Scheduler负责将Task分配到相应的 Worker,最后提交给StandaloneExecutorBackend执行;

8)对task进行序列化,并根据task的分配算法,分配task 9executor对接收过来的task进行反序列化,把task封装成一个线程; 10)开始执行Task,并向SparkContext报告,直至Task完成; 11)资源注销

2Spark on YARN运行过程(架构)

Spark on YARN模式根据Driver在集群中的位置分为两种模式:一种是YARN-Client模式,另一种是YARN- Cluster(或称为YARN-Standalone模式)。

YARN-Client模式

Yarn-Client模式中,Driver在客户端本地运行,这种模式可以使得Spark Application和客户端进行交互, 因为Driver在客户端,所以可以通过webUI访问Driver的状态,默认是 http://hadoop1:4040 访问,而 YARN通过 http:// hadoop1:8088 访问。

YARN-client的工作流程分为以下几个步骤:

1Spark Yarn ClientYARNResourceManager申请启动Application Master。同时在SparkContent初始化 中将创建DAGSchedulerTASKScheduler等,由于我们选择的是Yarn-Client模式,程序会选择 YarnClientClusterSchedulerYarnClientSchedulerBackend

2ResourceManager收到请求后,在集群中选择一个NodeManager,为该应用程序分配第一个 Container,要求它在这个Container中启动应用程序的ApplicationMaster,与YARN-Cluster区别的是在该 ApplicationMaster不运行SparkContext,只与SparkContext进行联系进行资源的分派;

3Client中的SparkContext初始化完毕后,与ApplicationMaster建立通讯,向ResourceManager注册,根 据任务信息向ResourceManager申请资源(Container);

4)一旦ApplicationMaster申请到资源(也就是Container)后,便与对应的NodeManager通信,要求它在 获得的Container中启动启动CoarseGrainedExecutorBackendCoarseGrainedExecutorBackend启动后会向 Client中的SparkContext注册并申请Task

5Client中的SparkContext分配TaskCoarseGrainedExecutorBackend执行, CoarseGrainedExecutorBackend运行Task并向Driver汇报运行的状态和进度,以让Client随时掌握各个任务 的运行状态,从而可以在任务失败时重新启动任务;

6)应用程序运行完成后,ClientSparkContextResourceManager申请注销并关闭自己。

YARN-Cluster模式

YARN-Cluster模式中,当用户向YARN中提交一个应用程序后,YARN将分两个阶段运行该应用程序:第 一个阶段是把SparkDriver作为一个ApplicationMasterYARN集群中先启动;第二个阶段是由 ApplicationMaster创建应用程序,然后为它向ResourceManager申请资源,并启动Executor来运行Task 同时监控它的整个运行过程,直到运行完成。

YARN-cluster的工作流程分为以下几个步骤:

1Spark Yarn ClientYARN中提交应用程序,包括ApplicationMaster程序、启动ApplicationMaster的命 令、需要在Executor中运行的程序等;

2ResourceManager收到请求后,在集群中选择一个NodeManager,为该应用程序分配第一个 Container,要求它在这个Container中启动应用程序的ApplicationMaster,其中ApplicationMaster进行 SparkContext等的初始化;

3ApplicationMasterResourceManager注册,这样用户可以直接通过ResourceManage查看应用程序的 运行状态,然后它将采用轮询的方式通过RPC协议为各个任务申请资源,并监控它们的运行状态直到运 行结束;

4)一旦ApplicationMaster申请到资源(也就是Container)后,便与对应的NodeManager通信,要求它在 获得的Container中启动启动CoarseGrainedExecutorBackendCoarseGrainedExecutorBackend启动后会向 ApplicationMaster中的SparkContext注册并申请Task。这一点和Standalone模式一样,只不过 SparkContextSpark Application中初始化时,使用CoarseGrainedSchedulerBackend配合 YarnClusterScheduler进行任务的调度,其中YarnClusterScheduler只是对TaskSchedulerImpl的一个简单包 装,增加了对Executor的等待逻辑等;

5ApplicationMaster中的SparkContext分配TaskCoarseGrainedExecutorBackend执行, CoarseGrainedExecutorBackend运行Task并向ApplicationMaster汇报运行的状态和进度,以让 ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务;

6)应用程序运行完成后,ApplicationMasterResourceManager申请注销并关闭自己。

3YARN-Client YARN-Cluster 区别

理解YARN-ClientYARN-Cluster深层次的区别之前先清楚一个概念:Application Master。在YARN中,每 Application实例都有一个ApplicationMaster进程,它是Application启动的第一个容器。它负责和 ResourceManager打交道并请求资源,获取资源之后告诉NodeManager为其启动Container。从深层次的 含义讲YARN-ClusterYARN-Client模式的区别其实就是ApplicationMaster进程的区别。

YARN-Cluster模式下,Driver运行在AM(Application Master)中,它负责向YARN申请资源,并监督作业的运 行状况。当用户提交了作业之后,就可以关掉Client,作业会继续在YARN上运行,因而YARN-Cluster模式 不适合运行交互类型的作业;

YARN-Client模式下,Application Master仅仅向YARN请求Executor,Client会和请求的Container通信来调度 他们工作,也就是说Client不能离开。

Sparkyarn-cluster涉及的参数有哪些

--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--driver-memory 1g \
--executor-memory 1g \
--executor-cores 2 \
-queue default \

参数

解释

--class

程序的main方法所在的类

--master

指定 Master 的地址

--deploy-mode

指定运行模式(client/cluster

--driver-memory

Driver运行所需要的内存,  默认1g

--executor-memory

指定每个 executor 可用内存为 2g, 默认1g

--executor-cores

指定每一个 executor 可用的核数

--queue

指定任务的对列

Spark的阶段划分

这里说下Driver的工作流程,Driver线程主要是初始化SparkContext对象,准备运行所需的上下文,然后 一方面保持与ApplicationMasterRPC连接,通过ApplicationMaster申请资源,另一方面根据用户业务逻 辑开始调度任务,将任务下发到已有的空闲Executor上。

ResourceManagerApplicationMaster返回Container资源时,ApplicationMaster就尝试在对应的 Container上启动Executor进程,Executor进程起来后,会向Driver反向注册,注册成功后保持与Driver 心跳,同时等待Driver分发任务,当分发的任务执行完毕后,将任务状态上报给Driver

Driver起来后,Driver则会根据用户程序逻辑准备任务,并根据Executor资源情况逐步分发任务。

一个RDD任务分为:ApplicationJobStage Task Application:初始化一个 SparkContext 就生成一个 Application Job:以Action方法为界,遇到一个Action方法则触发一个Job StageJob的子集,以RDD宽依赖(ShuVle)为界,遇到ShuVle做一次划分;

TaskStage的子集,以并行度(分区数)来衡量,分区数是多少,则有多少个task

Spark RDD通过其Transactions操作,形成了RDD血缘(依赖)关系图,即DAG,最后通过Action的调用, 触发Job并调度执行,执行过程中会创建两个调度器:DAGSchedulerTaskScheduler

DAGScheduler负责Stage级的调度,主要是将job切分成若干Stages,并将每个Stage打包成TaskSet TaskScheduler调度。 TaskScheduler负责Task级的调度,将DAGScheduler给过来的TaskSet按照指定的调度策略分发到 Executor上执行,调度过程中SchedulerBackend负责提供可用资源,其中SchedulerBackend有多种 实现,分别对接不同的资源管理系统。

Driver初始化SparkContext过程中,会分别初始化DAGSchedulerTaskSchedulerSchedulerBackend以及 HeartbeatReceiver,并启动SchedulerBackend以及HeartbeatReceiverSchedulerBackend通过 ApplicationMaster申请资源,并不断从TaskScheduler中拿到合适的Task分发到Executor执行。 HeartbeatReceiver负责接收Executor的心跳信息,监控Executor的存活状况,并通知到TaskScheduler

Spark join的分类

 Spark join方式主要有以下三种:

hash join是传统数据库中的单机join算法,在分布式环境下需要经过一定的分布式改造,说到底就是尽 可能利用分布式计算资源进行并行化计算,提高总体效率。hash  join分布式改造一般有两种经典方案:

broadcast hash join:将其中一张小表广播分发到另一张大表所在的分区节点上,分别并发地与其上的分 区记录进行hash      joinbroadcast适用于小表很小,可以直接广播的场景。

1Broadcast Hash Join

broadcast hash join可以分为两步:

1broadcast阶段:将小表广播分发到大表所在的所有主机。广播算法可以有很多,最简单的是先发给 driverdriver再统一分发给所有executor;要不就是基于bittorretep2p思路;

2hash    join阶段:在每个executor上执行单机版hash   join,小表映射,大表试探。
适用于小表与大表的joinSparkSQL规定broadcast hash join执行的基本条件为被广播小表必须小于参数 spark.sql.autoBroadcastJoinThreshold,默认为10M,本质上是去用空间换时间,

缺点 : 小表需要建立索引,由于需要在 Driver 节点进行 collect ,所以需要保证 Driver 节点内 存充足,可在 spark-commit 提交执行任务时,通过设置 driver-memory 调节 Driver 节点大小。Map-Join 同时需要将经过 Map 广播到不同的 executor ,Task 获取数据进行连接并输出结果。所以 executor 也需要保证内存充足,可在 spark-commit 提交执行任务时,通过设置 --executor-memory 调节 Driver 节点大小。

2Shuffle Hash Join

 spark.shuffle.consolidateFiles 。该参数默认值为false

shuffle hash join:一旦小表数据量较大,此时就不再适合进行广播分发。这种情况下,可以根据join key相同必然分区相同的原理,将两张表分别按照join key进行重新组织分区,这样就可以将join分而治 之,划分为很多小join,充分利用集群资源并行化。

适合于没有特别小的两个表进行关联的时候,默认设置的Shuffle partition的个数是200,也就是分了200 个区,然后两张表的key值分别去基于200hash取余然后散步在每个区域中了,这样的思想先把相近的 合并在一个区内,再在每个分区内去做比较key值的等值比较,就避免了大范围的遍历比较,节省了时 间和内存。
缺点,生产文件过多大量小文件随机读写磁盘开销,数据块写入缓存,对内存造成压力。

3Sort-Merge Join

SparkSQL对两张大表join采用了全新的算法:sort-merge 

1Shuffle阶段:将两张大表根据join key进行重新分区,两张表数据会分布到整个集群,以便分布式并 行处理;

2sort阶段:对单个分区节点的两表数据,分别进行排序;

3merge阶段:对排好序的两张分区表数据执行join操作。join操作很简单,分别遍历两个有序序列,碰 到相同join     keymerge输出,否则取更小一边

这种适用于关联的两张表都特别大时,使用上述的两种方法加载到内存的时候对于内存的压力都非常大 时,因此在2方法的基础上,hash取余之后还要分别对两张表的key值进行排序,这样去做等值比较的时 候就不需要将某一方的全部数据都加载到内存进行计算了,只需要取一部分就能知道是否有相等的(比 如按升序排列,某个值明显比它大了,后面肯定就不会有相等的,就不用继续比较了,节省了时间和内 存),也就是在进行等值比较的时候即用即丢的。这个方法在前面进行排序的时候可能会消耗点时间, 但相对于后面的时间来说,总体是大大节省了时间。

2bypass SortShuffle bypass运行机制的触发条件如下:

Shuffle reduce task数量小于spark.Shuffle.sort.bypassMergeThreshold参数的值,默认为200

不是聚合类的Shuffle算子(比如reduceByKey

而该机制与普通SortShuffleManager运行机制的不同在于:不会进行排序。也就是说,启用该机制的最 大好处在于,Shuffle write过程中,不需要进行数据的排序操作,也就节省掉了这部分的性能开销。

优点

小文件的数量大量减少,Mapper   端的内存占用变少;

Spark      不仅可以处理小规模的数据,即使处理大规模的数据,也不会很容易达到性能瓶颈。

缺点

如果 Mapper Task 的数量过大,依旧会产生很多小文件,此时在 Shuffle 传数据的过程中到 Reducer 端, Reducer 会需要同时大量地记录进行反序列化,导致大量内存消耗和 GC 负担巨大, 造成系统缓慢,甚至崩溃;

强制了在 Mapper 端必须要排序,即使数据本身并不需要排序; 它要基于记录本身进行排序,这就是 Sort-Based Shuffle 最致命的性能消耗。

spark数据倾斜

1.预先处理,过滤脏数据

2.提高reduce端并行度reduceByKey(500)

3.使用随机key实现双重聚合(仅仅适用于聚合类 的shuffle操作groupByKeyreduceByKey)

        通过map算子给每个数据的key添加随机数前缀,对key进行打散,将原先一样的key变成不一样的 key,然后进行第一次聚合,这样就可以让原本被一个task处理的数据分散到多个task上去做局部聚合 随后,去除掉每个key的前缀,再次进行聚合

4.reduce join转换为map join

        不使用join算子进行连接操作,而使用Broadcast变量与map类算子实现join操作,进而完全规避掉shuffle 类的操作,彻底避免数据倾斜的发生和出现。

        将较小RDD中的数据直接通过collect算子拉取到Driver端的 内存中来,然后对其创建一个Broadcast变量;接着对另外一个RDD执行map类算子,在算子函数内,从 Broadcast变量中获取较小RDD的全量数据,与当前RDD的每一条数据按照连接key进行比对,如果连接 key相同的话,那么就将两个RDD的数据用你需要的方式连接起来

宽依赖,窄依赖

相比于宽依赖,窄依赖对优化还有以下几点优势:

宽依赖往往对应着Shuffle操作,需要在运行过程中将同一个父RDD的分区传入到不同的子RDD分区 中,中间可能涉及多个节点之间的数据传输;而窄依赖的每个父RDD的分区只会传入到一个子RDD 分区中,通常可以在一个节点内完成转换。

RDD分区丢失时(某个节点故障),spark会对数据进行重算。

对于窄依赖,由于父RDD的一个分区只对应一个子RDD分区,这样只需要重算和子RDD分区对 应的父RDD分区即可,所以这个重算对数据的利用率是100%的;

对于宽依赖,重算的父RDD分区对应多个子RDD分区,这样实际上父RDD 中只有一部分的数据 是被用于恢复这个丢失的子RDD分区的,另一部分对应子RDD的其它未丢失分区,这就造成了 多余的计算;

更一般的,宽依赖中子RDD分区通常来自多个父RDD分区,极端情况下,所有的 父RDD分区都要进行重新计算。

为什么要划分Stage,

stage数量=宽依赖数据+1

由于一个job任务中可能有大量的宽窄依赖,窄依赖不会产生Shuffle,宽依赖会产生Shuffle。后期划分完 stage之后,在同一个stage中只有窄依赖,并没有宽依赖,这些窄依赖对应的task就可以相互独立的取运 行。划分完stage之后,它内部是有很多可以并行运行task

Spark容错机制?

1Lineage机制(简称血统机制)

RDDLineage机制是将粗颗粒度相同的操作(map flatmap filter之类的)记录下来,万一RDD信息丢失 可通过Lineage获取信息从新获得原来丢失的RDD

缺点:lineage如果过长 影响性能,开销太大

2checkpoint机制 RDD的结果存入HDFS,以文件的形式存在

3cache机制

将结果存入内存

4persist机制

将结果存入磁盘

checkpoint cache persist的异同 相同点:都要在action算子之后触发 不同点

checkpoint

是存在HDFS上的,更加安全可靠,并且checkpoint会改变依赖关系,并且之后会触发一个job操作

persistcache

不改变依赖关系,运行完成后缓存数据自动消失

Spark SQL的执行原理?

近似于关系型数据库,见下图,Spark SQL语句由Projectiona1a2a3)、Data SourcetableA)、 Filtercondition)组成,分别对应SQL查询过程中的ResultData SourceOperation,也就是说,SQL 语句按指定次序来描述,如Result->Data Source->Operation

 

执行Spark SQL语句的顺序如下:

1对读入的SQL语句进行解析Parse),分辨出SQL语句中的关键词(如SELECTFROMWhere)、 表达式、ProjectionData Source等,从而判断SQL语句是否规范

2将SQL语句和数据库的数据字典(列、表、视图等)进行绑定(Bind),如果相关的Projection Data      Source等都存在的话,就表示这个SQL语句是可以执行的。

3选择最优计划。一般的数据库会提供几个执行计划,这些计划一般都有运行统计数据,数据库会在 这些计划中选择一个最优计划(Optimize)。

4计划执行(Execute)。计划执行案Operation->Data Source->Result的次序来执行,在执行过程中有时 候甚至不需要读取物理表就可以返回结果,如重新运行执行过的SQL语句,可直接从数据库的缓冲池中 获取返回结果。

Spark SQL的数据倾斜解决方案:

聚合源数据:Spark CoreSpark SQL没有任何区别 过滤导致倾斜的key:在sql中用where条件 提高Shuffle并行度:groupByKey(1000)spark.sql.Shuffle.partitions(默认是200 双重groupBy:改写SQL,两次groupBy

reduce join转换为map joinspark.sql.autoBroadcastJoinThreshold(默认是10485760);可以自己 将表做成RDD,自己手动去实现map joinSparkSQL内置的map  join,默认如果有一个10M以内的小 表,会将该表进行broadcast,然后执行map join;调节这个阈值,比如调节到20M50M、甚至  1G

采样倾斜key并单独进行join:纯Spark Core的一种方式,samplefilter等算子 随机key与扩容表:Spark SQL+Spark Core

Spark checkpoint

可回答:Spark Streamingcheckpoint 问过的一些公司:顺丰,竞技世界,哈啰 参考答案: 1、先看下checkpoint到底是什么?

1Spark在生产环境下经常会面临TranformationsRDD非常多(例如,一个Job中包含10 000RDD)或 者具体Tranformation产生的RDD本身计算特别复杂和耗时(例如,计算时常超过1h),此时我们必须考 虑对计算结果数据的持久化。

2Spark擅长多步骤迭代,同时擅长基于Job的复用,这时如果能够对曾经计算的过程产生的数据进行 复用,就可以极大地提升效率。

3)如果采用persist把数据放在内存中,虽然是最快速的,但是也是最不可靠的。如果放在磁盘上,也不 是完全可靠的。例如,磁盘会损坏,管理员可能清空磁盘等。

4checkpoint的产生就是为了相对更加可靠地持久化数据,checkpoint可以指定把数据放在本地并且是 多副本的方式,但是在正常的生产情况下是放在HDFS,这就自然地借助HDFS高容错、高可靠的特征完 成了最大化的、可靠的持久化数据的方式。

5)为确保RDD复用计算的可靠性,checkpoint把数据持久化到HDFS中,保证数据最大程度的安全性。

6checkpoint就是针对整个RDD计算链条中特别需要数据持久化的环节(后面会反复使用当前环节的 RDD)开始基于HDFS等的数据持久化复用策略,通过对RDD启动checkpoint机制来实现容错和高可用。

至于Sparkcheckpoint源码详解可以参考《Spark大数据商业实战三部曲》9.2小结,讲的很详细

2checkpoint运行流程图如下图所示

 

通过SparkContext设置Checkpoint数据保存的目录,RDD调用checkpoint方法,生产 RDDCheckpointData,当RDD上运行一个Job后,就会立即触发RDDCheckpointData中的checkpoint方法, 在其内部会调用doCheckpoint;然后调用ReliableRDDCheckpointDatadoCheckpointReliableCheckpointRDDwriteRDDToCheckpointDirectory的调用;在writeRDDToCheckpointDirectory方法 内部会触发runJob,来执行把当前的RDD中的数据写到Checkpoint的目录中,同时会产生 ReliableCheckpointRDD实例。

checkpoint保存在HDFS中,具有多个副本;persist保存在内存中或者磁盘中。在Job作业调度的时候, checkpoint沿着finalRDD血统关系lineage从后往前回溯向上查找,查找哪些RDD曾标记为要进行 checkpoint,标记为checkpointInProgress;一旦进行checkpointRDD所有父RDD就被清空。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值