Spark知识点总结
1.Spark基本架构
- Cluster Manager : Spark的集群管理器, 主要负责对整个集群资源的分配与管理. Cluster Manager分配的资源属于一级资源, 它将各个Worker上的内存, CPU分配给Application, 但不负责对Executor的资源分配. 在standalone模式下即为Master主节点, 控制整个集群, 监控Worker.
- Worker: Spark的工作节点. 主要负责管理本节点. 1.将自己的内存, CPU等资源通过***制告知Cluster Manager. 2.创建Executor, 并分配资源给Executor. 3.同步资源信息, Executor信息给Cluster Manager.
- Executor: 执行器, 是为某个Application运行在Worker上的JVM进程. 负责任务的执行, 与Worker, Driver的信息同步
- Driver: Application的驱动程序, Application通过Driver与Cluster Manager, Worker进行通信. Driver可以运行在Application中, 也可以由Application提交给Cluster Manager, 并由Cluster Manager安排Worker运行
- Application: 用户编写的Spark程序. Application通过Spark的API进行RDD的转换和DAG的构建, 通过Driver将Application注册到Cluster Manager. Cluster Manager会根据Application的资源需求, 通过一级分配将Executor, 内存, CPU分配给Application. Driver通过二级分配将Executor等资源分配给每一个任务. Application最后通过Driver告诉Executor运行任务
2.Spark RDD
Resilient Distributed Datasets, 弹性分布式数据集. 是分布式内存的一种抽象概念, 是只读的记录分区的集合, 能横跨集群的所有节点进行并行计算, 是一种基于工作集的应用抽象
RDD的几个属性:
- 1.一组分片(Partition): 数据集的基本组成单位. 对于RDD来说, 每个分片都会被一个计算任务(Task)处理, 分区的数量决定了并行计算的粒度. RDD的并行度默认从父RDD传递给子RDD. 默认情况下, HDFS上的一个数据分片(Block)就是一个partition. 也可以在创建RDD的时候指定分片个数.
- 2.一个作用于每个分片的函数: RDD中的计算是以分片为单位的, 每个RDD都会实现compute函数, RDD的分片是并行计算的.
- 3.RDD间的依赖关系: RDD的每次转换都会生成一个新的RDD, 所以RDD之间就会形成流水线式的依赖关系. 在部分分区数据丢失时, 可以通过RDD间的依赖关系重新计算丢失的分区数据, 而不用对RDD的所有分区重新计算.
- 4.一个Partitioner: RDD的分片函数, 只有key-value形式的RDD才会有Partitioner. Partitioner不止决定了RDD本身的分片数量, 也决定了parent RDD shuffle输出时的分片数量.
- 5.一个存储每个Partition的优先位置列表(preferred location): 对于一个HDFS文件来说, 这个列表保存的就是每个partition所在的块的位置. Spark在进行任务调度的时候, 会尽可能地将计算任务分配到其所要处理的数据块的存储位置(移动数据不如移动计算)
对于 RDD 可以有两种操作算子: 转换(Transformation)与行动(Action)
- 转换(Transformation): Transformation操作是延迟计算的, 也就是说从一个RDD转换生成另一个RDD的转换操作不是马上执行, 需要等到Action操作的时候才会真正触发运算.
- 行动(Action): Action算子会触发Spark提交作业(Job), 并将数据输出Spark系统.
RDD的创建方式
- 1.从Hadoop文件系统(HDFS)创建
- 2.从父RDD转换得到新RDD
- 3.通过parallelize或makeRDD将单机数据创建为分布式RDD
RDD处理流程
- 1.创建RDD对象
- 2.DAGScheduler模块介入运算, 计算RDD间的依赖关系, RDD间的依赖关系形成了DAG
- 3.每一个Job被划分为多个stage的task, 划分stage的主要依据是当前计算因子的输入是否是确定的, 如果是则将其分在同一个Stage, 避免多个Stage间的消息传递开销.将TaskSet交由TaskScheduler, Cluster Manager再分配给Worker资源, 并从SparkContext获取Task执行.
3.Spark运行流程
- 1.构建Spark Application的运行环境(启动Driver), Driver向资源管理器(可以是Standalone, Mesos或YARN)注册并申请Executor资源.
- 2.资源管理器分配Executor并启动StandaloneExecutorBackend, 运行情况随着心跳发送到资源管理器上
- 3.Driver构建DAG, 将DAG分解成多个Stage, 并把TaskSet发送给TaskScheduler, Executor向SparkContext申请Task
- 4.TaskScheduler将Task发送给Executor运行同时Driver将程序代码发送给Executor
- 5.Task在Executor上运行, 运行完毕释放所有资源
Spark的运行特点:
- 每个Application获取专属的executor进程, 该进程在Application期间一直驻留, 并以多线程方式运行tasks. 这种Application隔离机制是有优势的. 从调度角度看, 每个Driver调度它自己的任务, 且不同的Application运行在不同的JVM中. 但这也意味着不同的Spark Application间不能跨应用程序共享数据
- 提交SparkContext的Client应该靠近Worker节点.因为Spark运行期间SparkContext和Executor间有大量的信息交换.
- Task采用了数据本地性和推测执行的优化机制.
4.ShuffleDependency和NarrowDependency
- 窄依赖是指每一个父RDD的Partition只会被一个子RDD的Partition使用(一子一亲)或者一个子RDD的Partition使用多个父RDD的Partiton(一子多亲)
- 宽依赖是指多个子RDD的Partition会使用同一个父RDD的Partition(多子一亲)
窄依赖因为有shuffle操作, 需要跨网络拉取数据, 比较耗资源. 例如reduceByKey grupByKey combineByKey,sortByKey, join(no copartition)
窄依赖可以直接在同一个节点完成转换, 速度比较快. 例如filter map flatmap mapPartitions