Spark特点
1.速度快
基于内存计算,速度较MapReduce快100倍
2.易于使用
使用Scala语言编写,使用较少的代码量就可以实现较为复杂的业务。
3.生态完整
支持离线计算、支持微批处理下的实时计算、支持图计算和机器学习。
Spark core
RDD
spark的核心RDD:弹性分布式数据集,特点是不可变,可分区,里面元素并行计算的集合
弹性可介于内存和磁盘之间保存,内存不够可保存在磁盘上。
分布式可以进行分区。
数据集存放了计算逻辑,不存具体数据。
可并行计算多个分区可交由不同节点进行计算
血缘
多个RDD之间的依赖关系就形成了血缘关系,有两种:宽依赖和窄依赖
窄依赖
子RDD一个分区的数据只依赖于父RDD一个分区的数据,如map,filter这种一对一的算子。
宽依赖
子RDD一个分区的数据依赖于父RDD多个分区,会产生shuffle操作,例如reduce类的聚合算子。
transformation转换算子
在使用转换算子后并不会立刻计算,而是直到遇到执行算子才开始计算;每个转换算子的返回值都是RDD,执行算子的返回值为非RDD的其他对象。如reduceBykey,map等。
action执行算子
带动转换算子执行运算,会返回非RDD的元素,标记了RDD依赖链的结束;如reduce、foreach等。
DAG有向无环图
多个RDD之间通过血缘进行连接形成的依赖链条即为DAG有向无环图,本质就是描述了RDD的执行流程;一张DAG有向无环图以RDD开始Action执行算子结尾,一个Spark程序可能会产生多个DAG有向无环图。
持久化和检查点
持久化
缓存在计算中需要重用的RDD,加快计算速度;也提供了一定的容错,如果计算失败可以不要重新计算而改用缓存;依然存在依赖链条,可以继续根据依赖链回溯。
persist()
提供了几种缓存机制,包括默认使用java序列化缓存在内存上(MEMORY_ONLY)、使用SER序列化缓存到内存上(MEMORY_ONLY_SER)、使用java序列化缓存在内存和磁盘之间(MEMORY_AND_DISK)等。
cache()
底层调用的persist的无参构造,默认使用MEMORY_ONLY缓存,即使用java序列缓存到内存上。
检查点checkpoint()
在HDFS中保存RDD,不保存RDD的依赖链,是复制实现的高容错机制;错误恢复时可以使用最近的checkpoint进行恢复,不会随程序结束删除。
Spark任务调度
概述
在driver中对任务进行调度,最后发送给Executor执行;
Stage
使用DAG对宽依赖进行划分,从最后一个RDD开始,使用回溯方法,遇到窄依赖包含到当前stage,遇到宽依赖断开形成新stage。
DAGScheduler
基于DAG图划分Stage并以taskset的形式提交到TaskScheduler。
TaskScheduler
将taskset提交到集群运行并监控。
Application
Spark的应用程序,包含一个Driver和若干Executor。
Driver
向集群管理申请资源运行Executor;根据不同模式运行在master节点或worker节点
Executor
每个Executor执行一组task任务,一个worker节点可以有多个Executor。
共享变量
broadcast广播变量
在分布式计算中发放对象时候,每个Executor task都会发放一份,在对象比较大时会占用大量服务器资源。使用广播变量var bc=SparkContext.broadcast(obj),则每个Executor共享一份变量,降低了网络输出和服务器资源开销。使用bc.value取出对象计算。
注意的是,RDD不能直接被广播,因为RDD不保存数据,保存的是计算过程;需要使用collect算子转换为非RDD对象后才能广播。
accumulator累加器
分布式只写变量,Executor中的task不能访问累加器的值。普通对象只能在每个task中存一份副本,不能对driver中的变量实现更新操作。
使用方式:
val accu = sc.longAccumuator()
accu.add(参数)
也可通过继AccumulatorV2实现自定义累加器。