spark
1、环境搭建
local
- 本地测试
- 需要本地安装hadoop
standalone
-
使用spark自带资源管理框架
- Driver向Master申请资源
yarn
-
使用hadoop的yarn作为资源管理框架
- 提交任务 Driver去ResourceManasger中申请资源
-
通过实现applicationMaster接口往yarn里面提交任务
-
yarn-client
-
在本地打印运行日志
-
一般用于上线前测试
-
Driver在本地(提交任务的节点)启动
- Driver只负责任务调度
- 启动ApplicationMaster 为spark应用程序申请资源
-
-
yarn-cluster
-
日志不再本地打印
-
一般用于上线运行
-
Driver(ApplicationMaster)在集群启动
- Driver即负责资源申请也负责任务调度
-
2、RDD五大特性
1、RDD由一组分区组成
- 默认一个block对应rdd中的一个分区
2、算子实际上是作用每一个分区上的
- 每一个分区都由一个task处理
3、RDD之间有一系列的依赖关系
-
宽依赖
- 会产生shuffle
-
窄依赖
- 不会产生shuffle
-
用于切分Stage, 每一个Stage是一组可以进行并行计算的task,由宽依赖划分
4、分区类的算子只能作用于KV格式的RDD上
- GroupBYKey
- reduceByKey
- SortByKey
- join
5、spark为task的计算提供了最佳计算位置,移动计算而不是移动数据
3、spark比mr快
1、spark会尽量将数据保存到内存中进行计算
- 对多次使用的RDD进行缓存
2、粗粒度资源调度
- 粗粒度会使得资源利用不充分
3、DAG有向无环图
4、常用算子
转换算子:
懒执行,需要action算子触发
-
map mapPartition
-
filter
- 筛选变少
-
flatMap
- 展开变多
-
sample
- 抽样
-
groupByKey
-
reduceBykey
-
sortBy SortBykey
-
rePartition ,partitionBy(自定义分区器)
- 重新分区,会产生shuffle
-
union
- 不去重
-
join
-
mapValues
操作算子:
触发任务执行,每一个action算子都会触发一个任务
-
foreach foreachPartition
- 优化,创建外部链接时可用foreachPartition
-
saveAsTaxtFile
- 保存到hdfs
-
collect
- 将rdd的数据拉取到内存中,变成一个数组
-
reduce
-
count
-
sum
5、分区partition
1、有shuffle过程的算子可以自定义分区数,也可以继承上一个分区数
2、优先级
- 1、手动指定
2、spark.default.parallelism(设置的默认并行度)
3、继承的上一个分区数
3、repartition: 没有实际的业务逻辑,只是修改rdd分区数据,但是会产生shuffle
4、coalesce(shuffle=false): 一般用于合并小文件,不产生shuffle ,效率高
5、可自定义分区
- 可实现自定义逻辑,如相同的某个字段信息分到一个分区
6、缓存
1、RDD默认不保存数据
2、懒执行
cache
-
是一个转换算子,不会触发job,需要接收
-
持久化级别
-
1、cache 默认调用 persist(StorageLevel.MEMORY_ONLY)
-
2、可以直接调用persist选择缓存级别。一般DMEMORY_AND_DISK_SER
-
3、数据存在Excutor的内存或者磁盘中
-
4、是否序列化SER
-
压缩
- 1、好处:数据量变小,占用空间更小
- 2、序列化和反序列化需要浪费cpu执行时间
- 3、时间换空间
-
-
7、checkpoint
1、将RDD的数据写入hdfs
2、checkpoing会切断RDD依赖关系
checkpoint流程
- 1、当第一个job 执行完成之后会从后面向前回溯,如果rdd调用了checkpoint方法会被打上一个标记
- 2、另启动一个job重新计算这个rdd的数据,将rdd的数据保存到hdfs
- 3、后续的job 就可以直接使用checkpoint中的数据
- 一个action算子就会触发一个job
优化:在checkpoint之前先进行cache
8、cache和checkpoint区别
1、Cache缓存只是将数据保存起来,不切断血缘依赖。Checkpoint检查点切断血缘依赖。
2、 Cache缓存的数据通常存储在磁盘、内存等地方,可靠性低。
Checkpoint的数据通常存储在HDFS等高容错、高可用的文件系统,可靠性高。
9、主从节点
Driver
-
spark 程序的主程序
-
1、负责申请资源
- new SparkContext
-
2、负责任务调度
- 发送task到Excutor中执行
Excutor
-
spark应用程序执行器
-
standalone
- worker所在节点启动
-
yarn
- NodeManager所在节点启动
-
执行task任务,向Driver汇报task执行情况
10、累加器
在算子中修改Driver端一个普通变量不会生效
在Driver端定义累加器,在Executor端累加,再到Driver获取累加结果(需在action算子之后获取)
11、广播变量
当在算子内部使用到Driver的一个大变量的时候可以将这个变量广播,广播之后可以减少变量副本数
限制
- 1、只能在Driver端定义
- 2、只能在Executor读取,不能修改
获取流程
- 1、task在计算的过程中如果使用到广播变量,会去BlockManager中获取
- 2、如果BlockManager中没有这个广播变量,BM会去Driver端的BlockManagerMaster中获取
- 3、广播变量放在MemoryStore
- 4、后面的task如果再用到,就不需要重新拉取
应用场景
- map join(将小表广播)
12、资源分配和任务调度
资源分配
-
yarn-client
- 1、通过spark-submit提交任务
- 2、在本地启动Driver val sc = new SparkContext(conf)
- 3、Driver发请求给RM 启动AM
- 4、RM分配资源(Container)随机选择一个节点启动AM
- 5、AM向RM申请一批Container启动Excutor
- 6、AM连接其他的NodeManager分配资源启动Excutor
- 7、Excutor反向注册给Driver ,由Driver负责任务的调度和管理
- 8、开始任务调度(action算子触发)
-
yarn-cluster
-
1、提交Application,客户机发送请求到ResourceManager,请求启动ApplicationMaster
-
2、ResourceManager收到请求后随机选择一个NodeManager分配container,启动ApplicationMaster
-
3、启动container,并且启动ApplicationMaster(相当于Driver)
- 既负责资源申请也负责任务调度
-
4、AM向RM请求申请一批container(资源)以启动Executor,注意:这里的一批资源
根据所设置的–num-executors,数量决定 -
5、AM连接NodeManager来启动Executor,这里的NM相当于Spark standlone模式下的Worker节点
-
6、Executor反向注册到Driver
-
7、开始任务调度(action算子触发)
-
任务调度
-
1、当遇到一个action算子,启动job,开始任务调度
-
2、构建DAG有向无环图
-
3、DAGScheduler 根据宽窄依赖切分Stage (stage是一组可以并行计算的task)
-
4、DAGScheduler 将stage以taskSet的形式发送给TaskScheduler
-
5、TaskScheduler 根据本地化算法将task发送到数据所在节点去执行
-
6、TaskScheduler收集tasK执行情况
- 如果task失败TaskScheduler默认重试3次
- 如果重试3次之后还失败,由DAGScheduler重试stage 默认重试4次
- 如果是因为shuffle过程中拉取文件失败发生的异常,TaskScheduler不负责重试task,而是由DAGScheduler重试上一个stage
-
TaskScheduler 推测执行
- 如果有一个task执行很慢,TaskScheduler会再启动一个一样的task去竞争执行,谁先执行完,以谁的为准
13、BlockManager
管理范围
- 1、广播变量和累加器
- 2、RDD的缓存数据
- 3、shuffle过程中的文件
广播变量拉取流程
- 1、当task执行过程中使用到广播变量,会向Executor获取
- 2、如果Executor中没有,则Executor会去Driver拉取
- 3、由ConnectionManager建立连接
- 4、由BlockTransforService拉取数据
- 5、由MemoryStore管理数据
组件
- ConnectionManager
- BlockTransferService
- MemoryStore
- DiskStore
spark sql
1、概述
- 在RDD的基础上封装了Sql层,提供了DataFrameApi 和sql
- 与RDD类似,DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表 格,除了数据以外,还掌握数据的结构信息
2、写代码方式
- 1、在idea中编写代码,提交到集群中运行
- 2、在Spark-shell中写代码
- 3、在Spark-sql中写sql
3、整合Hive
- 获取hive的元数据
- 1、需要开启hive的元数据服务 nohup hive --service metastore >> metastore.log 2>&1 &
- 2、将hive-site.xml文件复制到spark/conf目录下
- 3、将mysql的驱动包复制到spark/lib目录下
spark 优化
代码优化
-
1、尽量避免创建重复的RDD
-
2、尽可能复用同一个RDD
-
3、对多次使用的rdd进行缓存
- 缓存级别一般使用 MEMORY_AND_DISK_SER
-
4、尽量避免使用shuffle类的算子
-
5、使用map-side预聚合的shuffle操作
-
6、使用高性能的算子
-
reduceBykey
-
foeachPartition
- 一般用于和外部数据库链接的时候
-
coalesce
- 合并小文件
-
-
7、广播大变量
- map join 没有shuffle过程
- 减少网络传输的性能开销
- 减少对Executor内存的占用开销
- 降低 GC的频率
-
8、使用Kryo优化序列化性能
-
9、优化数据结构
- 1、尽量使用字符串代替自定义的类
- 2、尽量使用基本数据类型代替字符串
- 3、尽量使用数组代替集合
-
10、使用高性能的库fastutil
参数优化
-
–num-executors
- 直接决定任务可以执行多快
- 1、一般指定50-100比较合适
- 2、num-executors * executor-cores 不能超过yarn 总的cpu数
- 3、num-executors * executor-memory 不能超过yarn总的内存 一般最多使用一半左右
-
–executor-memory
- 一般指定4G 到8G
-
–executor-cores
- 一般2-4个 保证每一个cpu 的内存分到的内存不低于2G
-
–driver-memory
- Driver内,用于存储广播变量
-
–conf spark.default.parallelism=100
- rdd shuffle之后reduce的数量
-
–conf spark.sql.shuffle.partitions=100
- spark sql shuffle之后reduce的数量
- 默认是200
-
–conf spark.storage.memoryFraction=0.4
- 持久化可以用的内存
-
–conf spark.shuffle.memoryFraction0.4
- shuffle阶段可以使用的内存
-
–conf spark.locality.wait=10
- task再Executor中执行等待时间
-
–conf spark.network.timeout=600s
- spark 网络链接的超时时间
数据倾斜优化
-
产生的原因
- 1、key分布不均
- 2、产生shuffle
-
1、使用hive ETL进行预处理
- mr比spark稳定
-
2、过滤少量导致数据倾斜的key
- key 不能影响业务
-
3、提高shuffle并行度
- 稀释
-
4、双重聚合
- 1、加前缀进行第一次聚合
- 2、去掉前缀进行第二次聚合
-
5、map join
- 只适合大表和小表关联
-
6、采样倾斜的key 并拆分join
- 使用大表和表的join
-
7、使用随机前缀和扩容RDD进行join