一、Spark概述
1.Spark 是什么
Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。
2.Spark and MapReduce
Spark 和Hadoop 的根本差异是多个作业之间的数据通信问题 : Spark 多个作业之间数据通信是基于内存,而 Hadoop 是基于磁盘。
可称MapReduce为一次性数据集计算
主要利用磁盘交互,磁盘IO非常影响性能
Spark会将数据结果保存到Memory
如果部署共享集群,可能造成资源不足的问题,对其它任务产生影响(不适合和Hadoop其他组件共同使用)
技术选型
在绝大多数的数据计算场景中,Spark 确实会比 MapReduce 更有优势。但是在实际的生产环境中,由于内存的限制,可能会由于内存资源不够导致 Job 执行失败,此时,MapReduce 其实是一个更好的选择,所以 Spark并不能完全替代 MR。
二、三大数据结构
- RDD : 弹性分布式数据集
- 累加器:分布式共享只写变量
- 广播变量:分布式共享只读变量
1.RDD
RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据处理模型。(最小的计算单元)
弹性:可以存在给定不同数目的分区、数据缓存的时候可以缓存一部分数据,也可以缓存全部数据。
⚫ 存储的弹性:内存与磁盘的自动切换;
⚫ 容错的弹性:数据丢失可以自动恢复;
⚫ 计算的弹性:计算出错重试机制;
⚫ 分片的弹性:可根据需要重新分片。
分布式:分区可以分布到不同的executor上执行,也就是不同的workwer/NM上。
数据集:RDD 封装了计算逻辑,并不保存数据
RDD中的数据是不可变的,RDD 封装了计算逻辑,是不可以改变的,想要改变,只能产生新的 RDD,在新的 RDD 里面封装计算逻辑是分区的。操作过程中不断形成新的RDD。
1.2 RDD三种算子
RDD的方法类型(API类型)
-
transformation (transformation 算子):转换操作
功能:有一个RDD产生一个新的RDD。不会触发job的执行,在这些类型的API调用过程中,只会构建RDD依赖,也称为构建RDD的执行逻辑图(DAG图),即依赖关系。
比较常见的转换算子有:map flat map reducebykey groupbykey
有一个典型的问题是reduceByKey 和 groupByKey 的区别?
-
action (action算子)::动作/操作
功能:触发rdd的job执行,并将rdd对应的job提交到executor上执行,最终的结果输出到其它文件系统,或者返回给driver.每次有一个action算子,spark监控页面上该应用的job页面上就会多一条job记录。
常见:
collect:收集数据到 Driver
foreach:分布式遍历 RDD 中的每一个元素
count:返回 RDD 中元素的个数
transformation 算子执行和DAG创建都是在driver上完成的。DAG中间过程的执行是在action算子提交之后,到executor上执行
- 控制算子:persist (RDD缓存/RDD持久化):
rdd将数据进行缓存操作或者清除缓存的rdd数据。或者数据进行了checkpoint(只在streaming中使用)
1.3 执行原理
Spark 框架在执行时,先申请资源,然后将应用程序的数据处理逻辑分解成一个一个的计算任务。然后将任务发到已经分配资源的计算节点上, 按照指定的计算模型进行数据计算。最后得到计算结果。
RDD 是 Spark 框架中用于数据处理的核心模型,接下来我们看看,在Yarn 环境中,RDD的工作原理
- 启动 Yarn 集群环境
- Spark 通过申请资源创建调度节点和计算节点
- Spark 框架根据需求将计算逻辑根据分区划分成不同的任务
- 调度节点将任务根据计算节点状态发送到对应的计算节点进行计算
RDD 在整个流程中主要用于将逻辑进行封装,并生成 Task 发送给Executor 节点执行计算
1.4 RDD 依赖关系
RDD 血缘关系
RDD 只支持粗粒度转换,即在大量记录上执行的单个操作。将创建 RDD 的一系列 Lineage(血统)记录下来,以便恢复丢失的分区。RDD 的 Lineage 会记录 RDD 的元数据信息和转换行为,当该 RDD 的部分分区数据丢失时,它可以根据这些信息来重新运算和恢复丢失的数据分区。
RDD 窄依赖
窄依赖表示每一个父(上游)RDD 的 Partition 最多被子(下游)RDD 的一个 Partition 使用,通常指一对一,多对一
常用方法:map、flatmap、filter、union、join等
RDD 宽依赖
宽依赖表示同一个父(上游)RDD 的 Partition 被多个子(下游)RDD 的 Partition 依赖,会引起 Shuffle,一对多和多对多
常用方法:xxxxByKey、join ( 不满足上面窄依赖join条件的join) 、repartition、distinct等
2.广播变量
3.累加器
三、Spark 运行架构
1 运行架构
Spark 框架的核心是一个计算引擎,整体来说,它采用了标准 master-slave 的结构。有俩大核心组件
Driver 表示 master,负责管理整个集群中的作业任务调度。
Executor 则是 slave,负责实际执行任务。
Driver
Spark 驱动器节点,用于执行 Spark 任务中的 main 方法,负责实际代码的执行工作。
Driver 在 Spark 作业执行时主要负责:
- 将用户程序转化为作业(job)
- 在 Executor 之间调度任务(task)
- 跟踪 Executor 的执行情况
- 通过UI 展示查询运行情况
实际上,我们无法准确地描述 Driver 的定义,因为在整个的编程过程中没有看到任何有关Driver 的字眼。所以简单理解,所谓的 Driver 就是驱使整个应用运行起来的程序,也称之为Driver 类。
Executor
Spark Executor 是集群中工作节点(Worker)中的一个 JVM 进程,负责在 Spark 作业中运行具体任务(Task),任务彼此之间相互独立。Spark 应用启动时,Executor 节点被同时启动,并且始终伴随着整个 Spark 应用的生命周期而存在。如果有 Executor 节点发生了故障或崩溃,Spark 应用也可以继续执行,会将出错节点上的任务调度到其他 Executor 节点上继续运行。
Executor 有两个核心功能:
- 负责运行组成 Spark 应用的任务,并将结果返回给驱动器进程
- 它们通过自身的块管理器(Block Manager)为用户程序中要求缓存的 RDD 提供内存式存储。RDD 是直接缓存在 Executor 进程内的,因此任务可以在运行时充分利用缓存数据加速运算。