SparkCore核心知识

一、Spark作业调度方式
1、local   测试或实验性质的本地运行模式
      local[N]   是用单机的多个线程来模拟Spark分布式计算,通常用来验证开发出来的应用程序逻辑上有没有问题。

       其中N代表可以使用N个线程,每个线程拥有一个core。如果不指定N,则默认是1个线程(该线程有1个core)。

example:
spark-submit 
--class JavaWordCount 
--master local[10] 
JavaWordCount.jar 
file:///tmp/test.txt 
2、standalone:指定节点
        使用SparkSubmit提交任务的时候(包括Eclipse或者其它开发工具使用new SparkConf()来运行任务的时候),Driver运行在Client

spark-submit 
--master spark://wl1:6066 
--deploy-mode cluster
3、Yarn
1)yarn client   测试中常用

         Spark跑在Hadoop集群中,所以为了做到资源能够均衡调度,会使用YARN来做为Spark的Cluster Manager,来为Spark的应用程序分配资源。

       在执行Spark应用程序前,要启动Hadoop的各种服务。由于已经有了资源管理器,所以不需要启动Spark的Master、Worker守护进程

       Driver是在客户端运行

spark-submit --master yarn --deploy-mode client
2)yarn cluster 生产中用

        spark-submit脚本提交,向yarn(RM)中提交ApplicationMaster程序、AM启动的命令和需要在Executor中运行的程序等

         Resource Manager在集群中的某个NodeManager上运行ApplicationMaster,该AM同时会执行driver程序。紧接着,会在各NodeManager上运行

spark-submit --master yarn --deploy-mode cluster
cluster和client的区别:

                    cluster:sparkcontext创建在yarn集群中

                    client:sparkcontext创建在本地

二、SparkRDD
1、Spark作业按照算子表示执行过程


 2、 分类
1、transformation

  概念:字面意思就是进行转换,将rdd由一个形态转化成另一个形态

常见的tranformation算子

flatMap:将行拆分为单词
map:是最常用的算子,将将原rdd的形态,转化为另外一种形态。

filter:过滤

sample:根据给定的随机种子seed,随机抽样出数量为frac的数据

union:返回一个新的数据集,由原数据集和参数联合而成 该union操作和sql中的union all操作一模一样(不去重)

groupByKey:对数组进行 group by key操作 慎用

reduceByKey:需要先进行一次本地的预聚合,每一个mapper(对应的partition)执行一次预聚合

join:打印关联的组合信息

sortByKey:进行排序

combineBykey:

注意:

使用combineByKey和aggregateByKey来模拟groupByKey和reduceByKey

不管combineByKey还是aggregateByKey底层都是使用combineByKeyWithClassTag来实现的

区别:

 1、本质上combineByKey和aggregateByKey都是通过combineByKeyWithClassTag来实现的,只不过实现的细节或者方式不大一样。

2、combineByKey更适合做聚合前后数据类型不一样的操作,aggregateByKey更适合做聚合前后数据类型一致的操作

       因为我们可以在combineByKey提供的第一个函数中完成比较复杂的初始化操作,而aggregateByKey的第一个参数是一个值

 3、我们使用时最简单的版本,而在实际生产过程中,一般都是相对比较复杂的版本,还有其它参数的,比如partitioner

2、action算子

  概念:字面意思就是执行,action的操作目的就是用来执行一个job作业的

常见的action算子

 reduce:执行reduce操作,返回值是一个标量
collect :将数据从集群中的worker上拉取到dirver中,所以在使用的过程中要慎用,意外拉取数据过大造成driver内存溢出
count :返回当前rdd中有多少条记录
take : 获取rdd前n条记录
first : take(1) 获取rdd中的第一条记录
savenAsTextFile:将RDD中的数据保存到文件系统中
countByKey:和readuceByKey效果相同,但reduceByKey是一个Transformation
foreach:遍历
3、RDD缓存
       Spark 速度非常快的原因之一,就是在不同操作中可以在内存中持久化或缓存个数据集。当持久化某个 RDD 后,每一个节点都将把计算的分片结果保存在内存中,并在对此 RDD 或衍生出的 RDD 进行的其他动作中重用。这使得后续的动作变得更加迅速。RDD 相关的持久化和缓存,是 Spark 最重要的特征之一。可以说,缓存是 Spark 构建迭代式算法和快速交互式查询的关键。

RDD 的缓存方式

        RDD 通过 persist 方法或 cache 方法可以将前面的计算结果缓存,但是并不是这两个方法被调用时立即缓存,而是触发后面的 action 时,该 RDD 将会被缓存在计算节点的内存中,并供后面重用。

        通过查看源码发现 cache 最终也是调用了 persist 方法,默认的存储级别都是仅在内存存储一份,Spark 的存储级别还有好多种,存储级别在 object StorageLevel 中定义的

 

4、Shared Variables(共享变量)
      在 Spark 程序中,当一个传递给 Spark 操作(例如 map 和 reduce)的函数在远程节点上面运行时,Spark 操作实际上操作的是这个函数所用变量的一个独立副本。这些变量会被复制到每 台机器上,并且这些变量在远程机器上的所有更新都不会传递回驱动程序。通常跨任务的读写变量是低效的,但是,Spark 还是为两种常见的使用模式提供了两种有限的共享变量:广播变(Broadcast Variable)和累加器(Accumulator)

1)Broadcast Variables(广播变量) 

      如果我们要在分布式计算里面分发大对象,例如:字典,集合,黑白名单等,这个都会由Driver 端进行分发,一般来讲,如果这个变量不是广播变量,那么每个 task 就会分发一份,这在 task 数目十分多的情况下 Driver 的带宽会成为系统的瓶颈,而且会大量消耗 task 服务器上的资源,如果将这个变量声明为广播变量,那么知识每个 executor 拥有一份,这个executor 启动的 task 会共享这个变量,节省了通信的成本和服务器的资源。

没有使用广播变量:

使用了广播变量之后:

如何定义和还原一个广播变量

  定义 :  val broadcast = sc.broadcast(a)

  还原:   val c = broadcast.value

 

2)Accumulators(累加器) 

       在 Spark 应用程序中,我们经常会有这样的需求,如异常监控,调试,记录符合某特性的数据的数目,这种需求都需要用到计数器,如果一个变量不被声明为一个累加器,那么它将在被改变时不会在 driver 端进行全局汇总,即在分布式运行时每个 task 运行的只是原始变量的一个副本,并不能改变原始变量的值,但是当这个变量被声明为累加器后,该变量就会有分布式计数的功能。
  正确的图解:

      

如果定义和还原一个累加器

  定义 :  val a = sc.longAccumulator(0)

  还原  :  val b = a.value

 

三、Spark作业执行过程
1、使用wordCount案例来说明spark作业的执行过程


对图的几点说明:

1)通过wordcount的执行流程,可以看到在执行reducekbykey的时候,在上游的rdd结束之后执行了一次类似于mr编程中的本地聚合combiner,这样可以减少网络中传递的数据量,提高spark作业的执行效率

2)从上图中看到,上下游rdd中对应的partition有依赖关系,spark中把rdd之间的依赖关系形成的这个图称之为rdd的lineage(血统)

     启动的依赖关系,有两种:宽依赖和窄依赖

      窄依赖:下游rdd中的partition只依赖直接上游rdd中的某一个人partition或常数个partition,把这种依赖关系称之为窄依赖

                     窄依赖对应的算子:窄依赖算子,比如常见的flatmap,map,filter,union

      宽依赖:下游rdd中一个partition中的数据依赖上游rdd中所有的partition中的数据,把这种关系称之为宽依赖

                     宽依赖对应的算子:款依赖算子,比如常见:join,reduceByKey,sortByKey,groupByKey

注意:宽依赖算子或者窄依赖算子是针对transformation而言的,而action是触发transformation执行的动因

3)宽依赖非常重要,是spark作业阶段划分的标志代码从后往前推,从action开始,到第一个宽依赖算子结束,我们叫做finalstage,resultstage,在该宽依赖左右就化划分成了两个阶段,右侧就是我们刚才提到的resultstage,左侧再来一遍,一直往前找,找到一个宽依赖就形成一个阶段。在执行过程中,自然就有例外,如果从action往前推,到头都没有宽依赖,自动产生一个阶段,这个阶段就是ResultStage,在阶段表示的时候,从前往后推,第一个阶段stage0,以此类推

 

2、Spark作业执行过程(详细)


(1)、将我们编写的程序打成 jar 包

(2)、调用 spark-submit 脚本提交任务到集群上运行

(3)、运行 sparkSubmit 的 main 方法,在这个方法中通过反射的方式创建我们编写的主类的实例对象,然后调用 main 方法,开始执行我们的代码(注意,我们的 spark 程序中的 driver就运行在 sparkSubmit 进程中)

(4)、当代码运行到创建 SparkContext 对象时,那就开始初始化 SparkContext 对象了

(5)、在初始化 SparkContext 对象的时候,会创建两个特别重要的对象,分别是:DAGScheduler和 TaskScheduler

【DAGScheduler 的作用】将 RDD 的依赖切分成一个一个的 stage,然后将 stage 作为 taskSet

提交给 TaskScheduler

(6)、在构建 TaskScheduler 的同时,会创建两个非常重要的对象,分别是 DriverActor 和ClientActor

【clientActor 的作用】向 master 注册用户提交的任务

【DriverActor 的作用】接受 executor 的反向注册,将任务提交给 executor

(7)、当 ClientActor 启动后,会将用户提交的任务和相关的参数封装到 ApplicationDescription对象中,然后提交给 master 进行任务的注册

(8)、当 master 接受到 clientActor 提交的任务请求时,会将请求参数进行解析,并封装成Application,然后将其持久化,然后将其加入到任务队列 waitingApps 中(FIFO先进先出)

(9)、当轮到我们提交的任务运行时,就开始调用 schedule(),进行任务资源的调度

(10)、master 将调度好的资源封装到 launchExecutor 中发送给指定的 worker

(11)、worker 接受到 Master 发送来的 launchExecutor 时,会将其解压并封装到 ExecutorRunner中,然后调用这个对象的 start(), 启动 Executor

(12)、Executor 启动后会向 DriverActor 进行反向注册

(13)、driverActor 会发送注册成功的消息给 Executor

(14)、Executor 接受到 DriverActor 注册成功的消息后会创建一个线程池,用于执行 DriverActor发送过来的 task 任务

(15)、当属于这个任务的所有的 Executor 启动并反向注册成功后,就意味着运行这个任务的环境已经准备好了,driver 会结束 SparkContext 对象的初始化,也就意味着 new SparkContext 这句代码运行完成

(16)、当初始化 sc 成功后,driver 端就会继续运行我们编写的代码,然后开始创建初始的 RDD,然后进行一系列转换操作,当遇到一个 action 算子时,也就意味着触发了一个 job

(17)、driver 会将这个 job 提交给 DAGScheduler

(18)、DAGScheduler 将接受到的 job,从最后一个算子向前推导,将 DAG 依据宽依赖划分成一个一个的 stage,然后将 stage 封装成 taskSet,并将 taskSet 中的 task 提交给 DriverActor

(19)、DriverActor 接受到 DAGScheduler 发送过来的 task,会拿到一个序列化器,对 task 进行序列化,然后将序列化好的 task 封装到 launchTask 中,然后将 launchTask 发送给指定的Executor

(20)、Executor 接受到了 DriverActor 发送过来的 launchTask 时,会拿到一个反序列化器,对launchTask 进行反序列化,封装到 TaskRunner 中,然后从 Executor 这个线程池中获取一个线程,将反序列化好的任务中的算子作用在 RDD 对应的分区上。
 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spark-Core文档是本人经三年总结笔记汇总而来,对于自我学习Spark核心基础知识非常方便,资料中例举完善,内容丰富。具体目录如下: 目录 第一章 Spark简介与计算模型 3 1 What is Spark 3 2 Spark简介 3 3 Spark历史 4 4 BDAS生态系统 4 5 Spark与Hadoop的差异 5 6 Spark的适用场景 6 7 Spark成功案例 6 第二章 Spark开发环境搭建 8 1 Spark运行模式 8 2 Spark环境搭建 8 2.1Scala的安装 8 2.2Spark的单节点配置 9 2.3Spark-Standalone集群配置 9 2.4Spark-on-Yarn模式配置 12 2.5Spark-on-Mesos模式配置 13 2.6Hive-on-Spark配置 13 第三章 Spark计算模型 15 1 RDD编程 15 1.1弹性分布式数据集RDD 15 1.2构建RDD对象 15 2RDD操作 15 2.1将函数传递给Spark 16 2.2了解闭包 16 2.3Pair RDD模型 17 2.4Spark常见转换操作 18 2.5Spark常见行动操作 20 2.6RDD持久化操作 21 2.7注意事项 23 2.7并行度调优 24 2.8分区方式 25 3Examle:PageRank 27 第四章 Spark编程进阶 29 1共享变量 29 1.1累加器 30 1.2广播变量 31 2基于分区进行操作 32 3与外部程序间的管道 33 4数值RDD的操作 34 5 Spark Shuffle机制 34 第五章 Spark调优与调试 39 1开发调优: 40 1.1调优概述 40 1.2原则一:避免创建重复的RDD 40 1.3原则二:尽可能复用同一个RDD 41 1.4原则三:对多次使用的RDD进行持久化 42 1.5原则四:尽量避免使用shuffle类算子 43 1.6原则五:使用map-side预聚合的shuffle操作 44 1.7原则六:使用高性能的算子 45 1.8原则七:广播大变量 46 1.9原则八:使用Kryo优化序列化性能 47 1.10原则九:优化数据结构 48 2资源调优 48 2.1调优概述 48 2.2 Spark作业基本运行原理 49 2.3资源参数调优 50 第六章 Spark架构和工作机制 52 1 Spark架构 52 1.1 Spark架构组件简介 52 1.2 Spark架构图 54 2 Spark工作机制 54 2.1 Spark作业基本概念 54 2.2 Spark程序与作业概念映射 55 2.3 Spark作业运行流程 55 3 Spark工作原理 55 3.1 作业调度简介 55 3.2 Application调度 56 3.3 Job调度 56 3.4 Tasks延时调度 56 第七章 Spark运行原理 57 1 Spark运行基本流程 57 2 Spark在不同集群中的运行架构 58 2.1 Spark on Standalone运行过程 59 2.2 Spark on YARN运行过程 60

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值