1.Spark 运行提交方式:
Yarn Cluster:driver运行在AM中,负责向Yarn申请资源,并监督作业运行状况,当用户提交完作用后,就关掉Client,作业会继续在yarn上运行。然而cluster模式不适合交互类型的作业。
Yarn Client:AM仅向yarn请求executor,client会和请求的container通信来调度任务,即client不能离开。
2.Spark和Hadoop作业之间的区别
2.1.hadoop的job
一个MapReduce程序就是一个job,而一个job里面可以有一个或多个Task,Task又可以区分为Map Task和Reduce Task
MapReduce中的每个Task分别在自己的进程中运行,当该Task运行完时,进程也就结束
2.2.spark的job
同样有job的概念,但这里的job和MR中的job不一样
一个Application和一个SparkContext相关联,每个Application中可以有一个或多个job,可以并行或串行运行job
Spark中一个Action可以触发一个job运行
在job里面包含多个stage,stage以shuffle进行划分,stage中包含多个Task,多个Task构成了Task Set
和MapReduce不一样,Spark中多个Task可以运行在一个进程里面,而且这个进程的生命周期和Application一样,即使没有job运行
优点:加快Spark运行速度,Task可以快速启动,并处理内存中数据
缺点:每个Application拥有固定数量的executor和固定数目的内存
3.Spark是什么
也是一个分布式的并行计算框架。spark是下一代的map-reduce,扩展了mr的数据处理流程。
MR有什么问题?
- 调度慢,启动map、reduce太耗时
- 计算慢,每一步都要保存中间结果落磁盘
- API抽象简单,只有map和reduce两个原语
- 缺乏作业流描述,一项任务需要多轮mr
Spark是什么
- 也是一个分布式的并行计算框架。
- spark是下一代的map-reduce,扩展了mr的数据处理流程。
- executor都是装载在container里运行,container默认内存是1G(参数yarn.scheduler.minimum-allocation-mb定义)。
- AM在Spark中叫driver,AM向RM申请的是executor资源,当分配完资源后,executor启动后,由spark的AM向executor分配task,分配多少task、分配到哪个executor由AM决定,可理解为spark也有个调度过程,这些task都运行在executor的坑里。
- Executor有线程池多线程管理这些坑内的task。
Spark的优势
1、减少磁盘I/O
2、增加并行度
mr: 任务是进程级别,
spark: 线程级别
3、避免重新计算
中间结果进行持久化到内存或者磁盘
4、可选的Shuffle和排序
MR如果有reducer阶段,就一定会按照key排序! 但是业务需要不要求key一定有序
spark:提供多种可选的shuffle方案。根据需求来选择
5、灵活的内存管理策略
堆外内存offheap 堆内内存onheap
存储内存storagememory 执行内存executionmemory
4.Spark的基本概念
Driver Program
- (驱动程序)是Spark的核心组件
- 构建SparkContext(Spark应用的入口,创建需要的变量,还包含集群的配置信息等)
- 将用户提交的job转换为DAG图(类似数据处理的流程图)
- 根据策略将DAG图划分为多个stage,根据分区从而生成一系列tasks
- 根据tasks要求向RM申请资源
- 提交任务并检测任务状态
Executor
- 真正执行task的单元,一个Work Node上可以有多个Executor
Stage
- 对应一个taskset
Taskset
- 对应一组关联的相互之间没有shuffle依赖关系的task组成
Task
- 任务最小的工作单元
Spark任务运行流程图解
5.Spark解决了什么问题
- 最大化利用内存cache。
- 中间结果放内存,加速迭代。
- 某结果集放内存,加速后续查询和处理,解决运行慢的问题。
- 更丰富的API(解决API单一问题)
- Transfomation变换的api,比如map可对每一行做变换,filter过滤出符合条件的行等,这些API实现用户算法,灵活。
- spark提供很多转换和动作,很多基本操作如Join,GroupBy已经在RDD转换和动作中实现。不需用户自己实现。
6.Spark核心
- Spark基于弹性分布式数据集(RDD)模型,具有良好的通用性、容错性与并行处理数据的能力
- RDD(Resilient Distributed Dataset):弹性分布式数据集(相当于集合),它的本质是数据集的描述(只读的、可分区的分布式数据集),而不是数据集本身
- RDD的关键特征:
- RDD使用户能够显式将计算结果保存在内存中,控制数据的划分,并使用更丰富的操作集合来处理
- 使用更丰富的操作来处理,只读(由一个RDD变换得到另一个RDD,但是不能对本身的RDD修改)
- 记录数据的变换而不是数据本身保证容错(lineage)
-
通常在不同机器上备份数据或者记录数据更新的方式完成容错,但这种对任务密集型任务代价很高
-
RDD采用数据应用变换(map,filter,join),若部分数据丢失,RDD拥有足够的信息得知这部分数据是如何计算得到的,可通过重新计算来得到丢失的数据
-
这种恢复数据方法很快,无需大量数据复制操作,可以认为Spark是基于RDD模型的系统
-
-
懒操作,延迟计算,action的时候才操作
-
瞬时性,用时才产生,用完就释放
-
Spark针对RDD提供两类操作:transformations和action
-
transformations是RDD之间的变换,action会对数据执行一定的操作
-
transformations采用懒策略,仅在对相关RDD进行action提交时才触发计算 每个RDD包含了数据分块/分区(partition)的集合,每个partition是不可分割的
-
-
每个RDD包含了数据分块/分区(partition)的集合,每个partition是不可分割的
-
实际数据块的描述(实际数据到底存在哪,或者不存在)其值依赖于哪些partition
-
-
与父RDD的依赖关系(rddA=>rddB)
-
宽依赖:B的每个partition依赖于A的所有partition
-
比如groupByKey、reduceByKey、join……,由A产生B时会先对A做shuffle分桶
-
- 窄依赖:B的每个partition依赖于A的常数个partition
-
比如map、filter、union……
-
-
7.Spark的RDD依赖关系
- 每个partition的计算就是一个task,task是调度的基本单位。
- partition:一份待处理的原始数据会被按照相应的逻辑切分成n份,每份数据对应到RDD中的一个Partition
- 若一个stage包含的其他stage中的任务已经全部完成,这个stage中的任务才会被加入调度。
- 遵循数据局部性原则,使得数据传输代价最小
- 如果一个任务需要的数据在某个节点的内存中,这个任务就会被分配至那个节点。
- 需要的数据在某个节点的文件系统中,就分配至那个节点。
由spark的AM来决定计算partition的task,分配到哪个executor上。
8.Spark的容错机制
- 如果此task失败,AM会重新分配task
- 如果task依赖的上层partition数据已经失效了,会先将其依赖的partition计算任务再重算一遍
- 宽依赖中被依赖partition,可以将数据保存HDFS,以便快速重构(checkpoint)
- 窄依赖只依赖上层一个partition,恢复代价较少;宽依赖依赖上层所有partition,如果数据丢失,上层所有partiton要重算。
- 可以指定保存一个RDD的数据至节点的cache中,如果内存不够,会LRU释放一部分,仍有重构的可能
9.Spark资源参数调优
- Executor的内存分为3块
- 第一块:让task执行代码时,默认占executor总内存的20%(Executor total cpu core 20% 我们写的代码)
- task通过shuffle过程拉取上一个stage的task的输出后,进行聚合等操作时使用,默认也是占20%(spark.shuffle.memoryFraction 20% 聚合操作)
- 让RDD持久化时使用,默认占executor总内存的60%(spark.storage.memoryFraction 持久化(内存,磁盘))
-
Task的执行速度和每个executor进程的CPU Core数量有直接关系,一个CPU Core同一时间只能执行一个线程,每个executor进程上分配到的多个task,都是以task一条线程的方式,多线程并发运行的。如果CPU Core数量比较充足,而且分配到的task数量比较合理,那么可以比较快速和高效地执行完这些task线程。
-
num-executors:该作业总共需要多少executor进程执行
-
–建议:每个作业运行一般设置5-~100个左右较合适
-
-
executor-memory:设置每个executor进程的内存,num-executors*num-executors代表作业申请的总内存量(尽量不要超过最大总内存的1/3~1/2)
-
建议:设置4G~8G较合适
-
-
executor-cores:每个executor进程的CPU Core数量,该参数决定每个executor进程并行执行task线程的能力,num-executors*executor-cores代表作业申请总CPU core数(不要超过总CPU Core的1/3~1/2 )
-
建议:设置2~4个较合适
-
-
driver-memory:设置Driver进程的内存
-
建议:通常不用设置,一般1G就够了,若出现使用collect算子将RDD数据全部拉取到Driver上处理,就必须确保该值足够大,否则OOM内存溢出
-
-
spark.default.parallelism:每个stage的默认task数量
-
建议:设置500~1000较合适,默认一个HDFS的block对应一个task,Spark默认值偏少,这样导致不能充分利用资源
-
-
spark.storage.memoryFraction:设置RDD持久化数据在executor内存中能占的比例,默认0.6,即默认executor 60%的内存可以保存持久化RDD数据
-
建议:若有较多的持久化操作,可以设置高些,超出内存的会频繁gc导致运行缓慢
-
-
spark.shuffle.memoryFraction:聚合操作占executor内存的比例,默认0.2
-
建议:若持久化操作较少,但shuffle较多时,可以降低持久化内存占比,提高shuffle操作内存占比
-
10.Spark开发调优
更多查看:https://blog.csdn.net/Yuan_CSDF/article/details/116767641
- 避免创建重复的RDD。
- 尽可能复用同一个RDD。
- 对多次使用的RDD进行持久化处理
- 避免使用shuffle类算子
- 在spark作业运行过程中,最消耗性能的地方就是shuffle过程
- 将分布在集群中多个节点上的同一个key,拉取到同一个节点上,进行聚合和join处理,比如groupByKey、reduceByKey、join等算子,都会触发shuffle。
- Broadcast+map的join操作,不会导致shuffle操作,但前提适合RDD数据量较小时使用。
- 将分布在集群中多个节点上的同一个key,拉取到同一个节点上,进行聚合和join处理,比如groupByKey、reduceByKey、join等算子,都会触发shuffle。
- 在spark作业运行过程中,最消耗性能的地方就是shuffle过程
- 使用map-side预聚合的shuffle操作
- 一定要使用shuffle的,无法用map类算子替代的,那么尽量使用map-site预聚合的算子
- 思想类似MapReduce中的Combiner
- 可能的情况下使用reduceByKey或aggregateByKey算子替代groupByKey算子,因为reduceByKey或aggregateByKey算子会使用用户自定义的函数对每个节点本地相同的key进行预聚合,而groupByKey算子不会预聚合.
- 使用Kryo优化序列化性能
- Kryo是一个序列化类库,来优化序列化和反序列化性能
- Spark默认使用Java序列化机制(ObjectOutputStream/ObjectInputStreamAPI)进行序列化和反序列化
- Spark支持使用Kryo序列化库,性能比Java序列化库高很多,10倍左右
11.Spark技术栈
Spark Core:基于RDD提供操作接口,利用DAG进行统一的任务规划
Spark SQL:Hive的表+ Spark的里。通过把Hive的HQL转化为Spark DAG计算来实现
Spark Streaming:Spark的流式计算框架
MLIB:Spark的机器学习库,包含常用的机器学习算法
GraphX:Spark图并行操作库