SparkCore相关

Spark专题

1、Spark理论基础

1.1、Spark基本概念
1.1.1、Application
(1)一个Application中可以有一到多个Job
(2)一个Application中可以出发多次Action,查发一次Action形成一个DAG,一个DAG对应一个Job
注意:应用程序的入口为用户所定义的main方法
1.1.2、Job
(1)触发一次Action形成一个完整的DAG,一个DAG对应一个Job
(2)一个job有多个stage,一个stage有多个Task
1.1.3、DAG
(1)有向无环图,对多个RDD转换过程和依赖关系的描述;
(2)触发Action就会形成一个完整的DAG,一个DAG就是一个Job。
1.1.4、stage
(1)任务执行阶段,顺序执行,限制性后面的在执行前面的;
(2)一个stage对应一个Taskset,一个taskset的task的数量取决于stage中最后一个RDD分区的数量。
1.1.5、Task
(1)保存同种计算逻辑的多个Task集合;
(2)一个Taskset中的Task计算逻辑都一样,计算数据不一样。
1.6、shuffle
作用:RDD上游的一个分区将数据给了下游的RDD的多个分区
shuffle过程:下游的task到上游拉取数据,不是上有task发送给下游的;
1.7、dependency
含义:依赖关系,父RDD和子RDD之间的依赖关系
1.8、RDD算子
RDD:保存计算的元数据
算子分类:
	1、Transformtion算子 - 不触发提交作业
		:map,flatmap,union,groupby,filter,distinct
	2、Action算子 - 触发提交作业
		:
1.9、partition - 分区
概念:分区式RDD内部并行计算的一个计算单元,是RDD数据集的逻辑分片	
	分区的格式:决定计算粒度	
	分区的个数:决定任务个数作用:通过相同的key放在相同节点,避免不同节点聚合key时进行shuffle操作产生的网络IO
  • 分区作用
    1、增加并行度:
    2、减少通信开销:
  • 分区原则:分区个数 = 集群中CPU核心数目
1.10、并行度
Spark作业最大并行度=executor个数*每个excutor的cpu core数	:
1、Spark的当前并行度取决于task数,而task数=分区数	
:2、Spark给官方推荐分区数为最大并行度的2-3倍,可以提交前计算的线程立刻倍后面的task使用,并且每个task处理的数据量会更少

在这里插入图片描述

1.2、Spark架构
1.2.1、架构设计

在这里插入图片描述
在这里插入图片描述
(1)Dirver

对Spark应用的整个执行过程进行管控,它是Spark应用程序的"master"。	
:在Spark应用执行时,Driver端会启动很多服务的master端,这些服务的slave端运行在Executor上,这些服务的slave会向Driver端对应的master注册或汇报运行状态信息	
1、通过运行Spark应用的main函数来启动Spark应用;	
2、向资源管理平台申请资源,并在Worker节点上启动Executor;	
3、创建SparkSession(包括SparkContext和SparkEnv),并对Spark应用进行规划,编排,最后提交到Executor端执行;	
4、收集Spark应用的执行状态,并返回执行结果;

(2)Executor

Executor是执行Spark应用的容器,
它的职责:就是根据Driver端的要求来启动执行线程,执行task计算,上报任务状态,并返回执行结果。

(3)Sparksession

SparkSession:Spark SQL的入口点。	
	开发Spark SQL应用程序时首先要创建的对象之一。
	在创建SparkSession时,会同时创建SparkContext和SparkEnv。

(4)Cluster Manager

集群资源管理器:负责为运行在资源管理跨框架上的应用程序分配资源。
  • 可选择

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bAPSRicd-1627817366296)(C:/Users/%E6%9D%8E%E6%B5%B7%E4%BC%9F/AppData/Roaming/Typora/typora-user-images/image-20210801162428987.png)]
(5)Worker

集群中任何可以运行人物的节点:根据Cluster Manager的指令分配资源,执行应用程序,释放资源。
1.2.2、运行架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ktYV5eHz-1627817366297)(C:/Users/%E6%9D%8E%E6%B5%B7%E4%BC%9F/AppData/Roaming/Typora/typora-user-images/image-20210801161254923.png)]

2、RDD基础

2.1、RDD基本概念
RDD的含义:不保存要计算的数据,保存元数据,即数据的描述信息和运算逻辑,比如数据要从哪里读取,怎么运算。RDD:可认为是一个代理,对RDD进行操作,相当于在Driver端先是记录下计算的描述信息,然后生成task,将task调度到Executor端才执行真正计算逻辑。

在这里插入图片描述

(1)只读:不能修改,只能通过转换生成新的RDD
(2)分布式:可分布在多台机器上进行处理
(3)弹性:计算过程内存不足时会和磁盘进行数据交换	
(4)基于内存:可以全部或部分缓存在内存中,在多次计算间重用
2.2、RDD产生背景
Mapreduce框架缺点:都是把中间结果写入到HDFS中,带来的大量的数据复制、磁盘IO和序列化开销;	
RDD:将具体的应用逻辑表达为一系列转换处理,不同RDD之间的转换操作形成依赖关系,可以实现管道化,比买你中间存储的结果,大大降低了数据复制、磁盘IO和序列化开销;
2.3、RDD特点

高效容错性:RDD的设计中,数据只读,不可修改,如果需要修改数据,必须从父RDD转换到子RDD,由此在不同RDD之间建立了血缘关系,不需要通过数据冗余的方式(比如检查点)实现容错,而只需要通过RDD父子依赖关系重新计算得到丢失的分区来实现容错,无需回滚整个系统,避免了数据复制的高开销中间结果可持久化存储到内存:数据在内存中的多个RDD操作之间进行传递,不需要落地到整个磁盘,避免了不必要的磁盘开销

2.4、RDD的执行过程

​ 采用了惰性调用,通过血缘关系链接起来的一系列RDD操作实现管道化,不用担心有过多中间数据;

​ 一个操作得到的结果不需要保存中间数据,直接管道化流入到下一个操作进行处理,保证了每个操作在处理逻辑的单一性;

1、启动pyspark;
2、从HDFS文件中读取数据创建一个RDD;
3、定义一个过滤函数;
4、对创建好的RDD进行转换操作得到一个新的RDD;
5、对转换后的RDD持久化6、行动操作,用于计算一个RDD集合中包含的元素个数

***3和4:构建起fileRDD和filterRDD之间的依赖关系,形成DAG图,这时候并没有发生真正的计算,只是记录转换的轨迹;
***5:count()是一个行动类型的操作,触发真正的计算,开始实际执行从fileRDD到filterRDD的转换操作,并把结果持久化到内存中,最后计算出filterRDD中包含的元素个数。
2.5、RDD的任务调度
1、创建RDD对象
2、SparkContext:计算RDD之间的依赖关系,构建DAG
3、DAGScheduler:DAG图分解成多个阶段,每个阶段包含了多个任务,每个任务会被任务调度器分发给各个工作节点上的Executor执行

在这里插入图片描述

DagScheduler切分stageTaskScheduler切分taskShceduler都在driver上
2.6、RDD操作
2.6.1、转换操作
  • 每一次转换操作,生成一个新的RDD

  • RDD惰性求值,整个转换过程只是记录了转换的轨迹,并不会发生真正的计算

(1)filter(func)

#筛选出满足函数func的元素,返回一个新的数据集
lines = lines.filterlambda line:"spark" in  line)

(2)map(func)

#每个元素传递到函数func中,并将结果返回为一个新的数据集
lines = lines.map(lambda x:x+10)lines = lines.map(lambda x:x.split(" "))

(3)flatmap(func)

#于map()相似,但每个输入元素都可以映射到0或多个输出结果
lines = lines.flatMap(lambda x:x.split(" "))

(4)groupByKey()

#应用于(k,v)键值对的数据集,返回一个新的(k,Iterable)形式的数据集
lines = lines.groupByKey()将key相同的值归并为列表

(5)reduceByKey(func)

#应用于(k,v)键值对的数据集,返回一个新的(k,v)形式的数据集,其中每个值是将每个key传递到函数func中进行聚合后的结果。
lines = lines.reduceByKey(**lambda a,b:a+b**)函数作用于key后面列表
2.6.2、行动操作

–执行真正计算的操作

(1)count()

#返回数据集中的**元素个数**lines.count()

(2)collect()

#以**数组**形式返回数据集中的**所有元素**lines.collect()

(3)first()

#返回数据集中的**第一个元素**lines.first()
2.6.3、持久化
  • 持久化RDD会被保存在计算节点内存中被后面操作重复使用;

  • 遇上第一个行动操作出发真正计算后,才会进行持久化

(1)持久化

RDD.cache()  #标记为持久化RDD.persist(MEMORY_AND_DISK):#将rdd作为反序列化对象存在JVM中,内存不足,保存在磁盘,先进先出

(2)移除持久化

RDD.unpersist()手动将持久化的RDD从缓存中移除
2.7、RDD分区
分区作用	:
(1)增加并行度,并行计算	
(2)减少通信开销,未分区时,需要涉及到大量的网络通信分区个数 = 集群中CPU核心数据	
	(1)local[n]:分区个数为n	
	(2)yarn:集群各种所有核心和2取较大值为分区数

3、Spark任务调度

3.1、Spark执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rV8twW4l-1627817366302)(C:/Users/%E6%9D%8E%E6%B5%B7%E4%BC%9F/AppData/Roaming/Typora/typora-user-images/image-20210730114144792.png)]

1、提交代码:使用spark-submit提交代码到服务器上

2、创建SparkContext:在SparkContest初始化的时候会创建DAGScheduler和TaskScheduler

3、创建Appliction:TaskScheduler会启动一个后台进程取集群Master注册Application,申请任务资源,比如CPU,内存等等

4、启动Executor:worker会启动executor,Executor反向注册到Dirver上,Driver结束SparkContext初始化,继续执行代码;

5、创建Job:每次执行到一个action算子,就会创建一个job,同时job会被提交到DAGScheduler

6、划分Stage:.DAGScheduler会使用划分算法,将job划分成多个stage,然后每个stage都会创建一个TaskSet,划分stage依据是分区间有无数据交互,也就是Shuffle过程

7、TaskSet分配:TaskScheduler会把TaskSet中的task通过task分配算法提交到Executor上运行,遵循"计算向数据靠拢",TaskScheduler会根据节点上的数据,将对于的任务丢到该节点上。

8、创建线程池:Executor会创建线程池执行task,每个都会task被封装成TaskRunner。*总的来说:Spark应用的执行就是stage分批次提交TaskSet到Executor,每个Task针对RDD的一个partition,执行定义的算子,直到所有问题完成

  • Spark的运行主要分为2部分 :

  • 1、一部分是驱动程序,其核心是SparkContext;另一部分是Worker节点上Task,它是运行实际任务的。

  • 2、程序运行的时候,Driver和Executor进程相互交互:运行什么任务,即Driver会分配Task到Executor,Driver 跟 Executor 进行网络传输; 任务数据从哪儿获取,即Task要从 Driver 抓取其他上游的 Task 的数据结果,所以有这个过程中就不断的产生网络结果.

  • Task调度
    在这里插入图片描述

task调度:开启一个线程循环,不断根据当前可用资源区TaskScheduler上取Task执行
3.2、Spark的资源配置

在这里插入图片描述

1、num-executors:总共申请多少个executor
2、executor-cores:单个Executor的cpu core数,默认一个core运行一个task
3、executor-memory:单个executor内存,多个task共享
4、parallelism:分区数,决定task有多少5、BC-变量:广播变量,一个executor一份,多个task共享
  • 资源配置注意点
1、太大内存(executor-memory>15G)	:资源浪费,影响其他业务:限制单个executor的内存不能超过14G
2、太大CPU核数(executor-core>5)	:丢失了并发的优势,例如:num-executor = 10,executor-cores=10	:申请等待时间和风险
3、太多的executor(num-executor>500)	:申请等待时间和风险	:每个executor都是独立的JVM,网络IO成本4、太多的分区(parallelism>executor*cores*(3-5))	:任务过细,轮数太多	:增加driver的维护压力
3.3、yarn-cluster运行流程

在这里插入图片描述

1、在客户端提交Application
2、向RM申请启动AM(RM管理整个集群的计算资源)
3、RM接收客户端的请求,随机找一台NodeManager启动Application Master
4、AM向RM申请资源,启动executor
5、RM返回executor所需要的资源
6、AM链接NM,启动Executor
7、Executor启动之后,反向注册AM(Dirver)
8、AM发送task,接收Task反馈的结果

4、shuffle原理及优化

  • shuffle:下一个 Stage 向上一个 Stage 要数据这个过程
  • shuffle时机:RDD存在宽依赖的时候
  • shuffle的种类:在spark-1.6版本之前,一直使用HashShuffle,在spark-1.6版本之后使用Sort-Base Shuffle
4.1、Spark shuffle内部原理

在这里插入图片描述
shuffle操作:

repartition,*ByKey,Join&cogroup
  • Spark Shuffle实例 - 词频统计
1、shuffle write:map Tasks,分区数为3	
	每一个ShuffleMapTask:都会产生一个data文件和index文件	
	合并:只是将该ShuffleMapTask的各个partition对应的分区文件合并到data文件而已
2、shuffle read:read Tasks

在这里插入图片描述
在这里插入图片描述

4.2、shuffle调优
1、数据落地时,partition数不易过多:在保存到hdfs前,尽量控制partition数,避免落地后小文件较多影响后续加载。落地前调用rdd.coalesce(num_partition)减少partition数	
2、主动shuffle-repartition:如果分区数少,可增大分区,将任务细分	:提高后续分布式运行的速度
3、调整shuffle read并发度:内存紧俏时,减少shuffle read并发	:内存充足时,增加shuffle read并发
4、多表join:如果要join多个RDD,请使用cogroup
5、避免使用groupBykey进行聚合操作	
	特征:groupbykey.mapvalues(_.sum)	
	改进:rdd.reduceBykey()

在这里插入图片描述

6、数据倾斜处理 - join	
	:对key进行分桶,将大数据量的key落地到一个主机上	
	缺点:小表会膨胀,整体运行缓慢

在这里插入图片描述

5、Broadcast原理及实践

  • Broadcast:用于处理共享配置文件

Broadcast:将数据从一个节点发送到其他的节点上例如 Driver 上有一张表,而 Executor 中的每个并行执行的Task (100万个Task) 都要查询这张表的话,那我们通过 Broadcast 的方式就只需要往每个Executor 把这张表发送一次就行了,Executor 中的每个运行的 Task 查询这张唯一的表,而不是每次执行的时候都从 Driver 中获得这张表!

5.1、Broadcast基本原理
  • No broadcast:每次启动都要传输大对象broadcast:每个executor传输一次大对象,并使用torrent加工网络传输
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K7YjZ1QT-1627817366312)(C:/Users/%E6%9D%8E%E6%B5%B7%E4%BC%9F/AppData/Roaming/Typora/typora-user-images/image-20210730144900857.png)]
    在这里插入图片描述
5.2、Broadcast实践 - 广播变量
  • 广播变量:实际上就是Driver端的变量通过Broadcast方法传输到Executor端,Executor端不能修改广播变量的值,使用广播变量是为了减少Executor端的数据备份,减少Executor端的内存。
  • 注意:如果任务逻辑中会使用比较大的对象(大于10M),例如静态查找表,则考虑将其变成广播变量
    在这里插入图片描述
5.3、Broadcast实践 - MapJoin
Mapjoin:会避免shuffle	传统join操作:会导致shuffle操作	Mapjoin操作:使用Broadcast甲肮一个数据量小的RDD作为广播变量
  • MapJoin处理数据倾斜
实现方式:将RDD分割成两部分进行join

在这里插入图片描述

6、Cache

  • 落地:将RDD保存到内存或者磁盘上
6.1、Cache基本原理
  • 基本原理:对多次使用的RDD进行持久化。
  • 此时Spark就会根据你的持久化策略,将RDD中的数据保存到内存或者磁盘中。以后每次对这个RDD进行算子操作时,都会直接从内存或磁盘中提取持久化的RDD数据,然后执行算子,而不会从源头处重新计算一遍这个RDD,再执行算子操作。

在这里插入图片描述
在这里插入图片描述

6.2、Cache原则
persist原则	
1、长链型的RDD,每个都不需要Cache,spark会链式执行	
2、树形的RDD,分叉处的RDD,精良Cache

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cBwuLpNl-1627817366319)(C:/Users/%E6%9D%8E%E6%B5%B7%E4%BC%9F/AppData/Roaming/Typora/typora-user-images/image-20210730171838746.png)]

6.3、Cache性能
内存充足时推荐:rdd.persist(StorageLevel.MEMORY_ONLY)
内存稀缺时推荐:rdd.persist(Storagelevel.MEMORY_ONLY_SER)

在这里插入图片描述

7、CheckPoint

  • 落地:将RDD保存到HDFS上
7.1、CheckPoint基本原理
  • 断链:随着迭代的进行,RDD依赖关系越来越长,driver维护压力变大,可能driverOOM,可能会断链

img

  • Checkpoint:针对整个RDD 计算链条中特别需要数据持久化的环节(后面会反覆使用当前环节的RDD) 开始基于HDFS 等的数据持久化复用策略,通过对 RDD 启动 Checkpoint 机制来实现容错和高可用;
  • 读取数据优先级:
    1、当RDD使用cache机制从内存中读取数据,
    2、如果数据没有读到,会使用checkpoint机制读取数据。
    3、此时如果没有checkpoint机制,那么就需要找到父RDD重新计算数据了,因此checkpoint是个很重要的容错机制。
7.2、CheckPoint的作用
元数据CheckPoint作用:通过保存在HDFS上的定义信息来恢复应用程序中运行worker的节点的故障,
	主要为了从driver故障中恢复
数据CheckPoint作用:通过保存在HDFS上的RDD来恢复断链造成的故障

在这里插入图片描述

7.3、cache与checkpoint的区别

cache与checkpoint的区别在于

  • 1、checkpoint会导致断链,执行checkpoint后不再保存依赖链
  • 前者持久化只是将数据保存在BlockManager中但是其lineage是不变的,但是后者checkpoint执行完后,rdd已经没有依赖RDD,只有一个checkpointRDD,checkpoint之后,RDD的lineage就改变了。
  • 2、持久化存储保存在内存或磁盘上在程序运行结束后就会自动删除,检查点保存的RDD状态保存在HDFS上,只能手动清理
  • :persist或者cache持久化的数据丢失的可能性更大,因为可能磁盘或内存被清理,但是checkpoint的数据通常保存到hdfs上,放在了高容错文件系统。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随缘清风殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值