运行模式:
local:适用于本地测试
yarn: 分为yarn-client、yarn-cluster两个模式。yarn-client的Driver驱动程序会在客户端进行运行,而yarn-cluster的驱动程序是在集群的(nodemanager)applicationMaster上面。
standalone:独立模式,spark客户端将任务提交到 Master/slaves结构的集群上的master处理,使用spark自身的调度系统。
spark任务提交的方式:J2ee还是shell?
shell
#!/bin/bash
# 设置Spark主节点URL和应用程序名称
SPARK_MASTER="spark://localhost:7077"
APP_NAME="MySparkApp"
# 设置其他Spark配置属性
SPARK_CONF="--executor-memory 2g --num-executors 4"
# 提交Spark应用程序
spark-submit \
--master $SPARK_MASTER \
--name $APP_NAME \
$SPARK_CONF \
path/to/your/app.jar
1)在提交任务时的几个重要参数
executor-cores —— 每个 executor 使用的内核数,默认为 1,官方建议 2-5 个,我们企业是 4 个 num-executors —— 启动 executors 的数量,默认为 2
executor-memory —— executor 内存大小,默认 1G
driver-cores —— driver 使用内核数,默认为 1
driver-memory —— driver 内存大小,默认 512M
2)一个提交任务的样式
spark-submit
\ --master local[5]
\ --driver-cores 2
\ --driver-memory 8g
\ --executor-cores 4
\ --num-executors 10
\ --executor-memory 8g
\ --class PackageName.ClassName XXXX.jar
\ --name "Spark Job Name"
\ InputPath
\ OutputPath
spark架构与作业提交流程简述
yarn-cluster模式
1.spark-submit 中main被执行
2.反射 Client类的main方法执行
3.向RM注册任务并加入队列
4.NM认领后创建AM,AM中的driver申请所需资源
5.同时会申请相应的executors并创建executor对象,这个executors会向driver注册
6.driver 执行代码 初始化SC 任务划分
7.分配对应任务给指定的executors执行
spark的血统(lineage)概念及其作用
lineage是记录分区之间依赖关系的机制,分为宽依赖和窄依赖;窄依赖是一个分区依赖一个分区,没有shuffle操作,流程图呈现是一条直线;宽依赖是一个分区依赖多个分区,可能涉及shuffle操作,产生更多的IO。
-
窄依赖(Narrow Dependency):
- 窄依赖表示父RDD的每个分区只被子RDD的一个或多个分区直接依赖。
- 窄依赖可以通过简单的转换操作(如map、filter)进行计算,不需要进行数据的洗牌操作(Shuffle)。
- 窄依赖保证了计算的高效性,因为父RDD的每个分区只需要被子RDD的一个或多个分区计算即可。
- 窄依赖在血统中以依赖关系图的一条直线表示。
-
宽依赖(Wide Dependency):
- 宽依赖表示父RDD的一个或多个分区被子RDD的多个分区依赖,需要进行数据的洗牌操作(Shuffle)。
- 宽依赖通常发生在一些需要进行分组、聚合或排序等操作的转换上,这些操作需要将父RDD的数据重新分配和重组。
- 宽依赖会引起数据的网络传输和磁盘读写,可能导致性能的下降。
- 宽依赖在血统中以依赖关系图的分叉表示。
lineage的作用主要是以下2点:
1.容错和数据恢复
lineage可以让spark在出错后根据依赖关系定位上次出错的地方重新执行,把丢失的数据找回来。
2.优化执行
可以根据lineage依赖关系优化执行计划,由于spark是惰性计算,故只需识别用到的部分,过滤掉多余的宽依赖来提高效率。
spark根据什么划分stage?根据什么划分tasks?
根据宽依赖划分,将job划分成若干个stage,每一个宽依赖都会对应一个stage;一个stage是taskSet,而task是根据RDD中的分区数将stage划分成数个tasks。
spark常用的transformation算子(惰性算法,不会马上执行),列举并说明其作用(功能)。
map(func)转化算子,每个输入元素,使用接受到的func函数的聚合逻辑按key分组合并value(做了转化),返回一个新的RDD。(元素数=map调用数)
分区:数据集被划分成若干个较小的数据块,即分区,每个分区可以在集群不同的节点上并行处理,并行度=分区数。
元素:即数据项,数据集被划分成若干个较小的数据块,数据块包含一定数量的元素,元素是数据集中一个个独立的数据项,是处理的基本单元,spark对每个元素进行计算转换,并存储在分区中。
mapPartitions(func)类似于map,但mapP是针对每个分区调用一次,即分区数=调用mapP数。
reduceByKey (func,numtasks)numtasks指定reduce任务数(并行数),func为聚合函数逻辑,按key聚合value,输入k-v类型rdd,返回一个新的k-v类型rdd。
def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) => U, combOp: (U, U) => U): RDD[(K, U)]
自定义函数,zeroV是初始值,seq是分区内聚合逻辑,comb是分区间聚合逻辑(将前两个value进行合并comb得到的结果与下一个value再一起传给comb,以此类推),返回一个k-v类型的rdd(key与计算结果作为一个新rdd)。
combineByKey 是一个做转化操作的算子,实现按键对数据集进行聚合计算。
def combineByKey[C](
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C): RDD[(K, C)]
createCombiner初始化函数,用于 将每个键转化成初始聚合格式
mergeValue是拿着初始聚合格式与分区内每个元素进行聚合。
mergeCombiners 分区间合并的聚合结果。
*combineByKey和aggregateByKey的区别在于 comb可以指定聚合格式,有三个参数,不需要初始值;agg需要有两个参数,以及一个初始值
spark常用的action算子(马上执行),列举并说明其作用(功能)。
reduce:reduce(func(a,b))接受一个函数func,对两个元素进行指定计算,得到结果再与下一个元素应用func,以此归约出最终的结果。action算子会马上执行。
*RDD与元素的关系: RDD说白了是数据集,里面的一个个数据项就是元素,RDD一创建就不可更改,想要修改,只能应用转换生成新的RDD,RDD是一个分布式数据集合。
collect:将存放在集群上各个节点的分区中的数据拉取到驱动程序中,使用数组存放,注意驱动程序的内存是否够用,否则数据量过大会内存溢出。
first:返回RDD中第一个分区的第一个元素,它不关心分区的顺序情况,若rdd为空,则抛异常。
take:take拉取RDD前N个元素,接受参数N,指定拿钱多少个元素出来,底层从远端拉取RDD中的元素到driver内存,应注意driver的内存大小与数据量的大小。
aggregate:
def aggregate[U](zeroValue: U)(seqOp: (U, T) => U, combOp: (U, U) => U): U
zeroValue初始值,seq分区内,comb分区间(全局)
注意分区间的操作也是基于初始化计算的。
count ByKey:行动算子,是按key计算key出现的次数,作用于一个RDD
foreach:对RDD中每个元素应用指定函数
saveAsTextFile:用于将RDD以Text的文件格式保存到指定路径,注意其中的操作保证幂等性
幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同
列举引起shuffle的算子,并简述功能。
1.聚合bykey类 reduceByKey groupByKey
2.集合表间交互(join、cogroup)
3.重分区repartition
4.去重、排序 sortByKey
简述spark核心hashShuffle和sortShuffle的工作流程,优化前后的差异。
hashShuffle未经优化:
1.分区数据进行哈希操作,确定数据需要发送到那个分区并落盘。
2.reduce任务拉取相应分区的磁盘上的数据。
优化后:
1.数据在每个executor 的多个task中处理时复用buffer缓冲区,减少落盘及溢写小文件的产生。
2.数据尽量存在内存,内存不足才会溢写到磁盘。
sortShuffle未经优化:
1.分区内做排序,现存内存,根据阈值判断是否溢写结果落盘
2.reduce拉取相应分区的磁盘上数据进行最终合并
优化后:bypass
如果输入数据的分区数小于或等于 Reduce 任务数的两倍(任务数少),就可以绕过分区排序操作,避免昂贵的排序操作,
直接将数据发送给reduce任务进行处理。
Spark 常用算子 reduceByKey 与 groupByKey 的区别,哪一 种更具优势?
reduceByKey是 分组聚合,shuffle之前会做combine预聚合处理,而groupByKey是分组,不会聚合,直接shuffle,故效率上reduceByKey更优。
但也要配合业务场景,因为仅仅分组的话,还是得用groupByKey。
repartition和coalesce的关系和区别:
都是用来改变rdd 的partition数量的, repartition底层调用的就是coalesce(numPartitions, shuffle =true)
repartition是宽依赖,增加或减少分区数,会触发shuffle
coalesce是窄依赖,合并或减少分区数,coalesce 根据传入的参数来判断是否发生 shuffle
分 别 简 述 Spark 中 的 缓 存 机 制 ( cache 和 persist ) 与 checkpoint 机制,并指出两者的区别与联系
cache 是临时缓存数据,在内存中,故发生错误,重新恢复后会失效,对于数据量大且高复用的场景,可以使用缓存避免重复计算。
ck是一种容错机制,在宕机后通过ck可以将RDD数据恢复到出错前的状态,继续处理,它会保存在磁盘。故CK会截断血统,避免血统过长
cache和ck都不会action,但cache会在计算节点间共享,而ck不会。cache适用于频繁使用的数据。ck适用于数据恢复的场景。