Spark -- (名词解释,以及RDD的概念)
名词解释
Standalone的cluster模式下的各个名词
Client:客户端进程,负责将作业提交给master
Master:主控节点,负责接收作业以及管理Worker,并命令worker启动Driver和Excutor
Worker:slave节点上的守护进程,负责管理本节点上的资源,定期向Master心跳反馈,接收Master的命令,启动Driver和Excutor,将任务执行的信息提交给Master
Driver:一个Spark的作业运行需要一个Driver,是作业的主进程,负责作业的解析,生成Stage并且调度Task到Excutor上。主要组件是SparkContext,SparkContext包含DAGScheduler和TaskScheduler
Excutor:真正执行作业的地方,一个Worker可以有多个Excutor,Excutor会启动一个线程池,就可以并行运行多个Task了
DAGScheduler:在Spark中,一个action算子就会解析成一个job,DAGScheduler将job分解成多个stage,每个stage根据分区的个数生成相应的Task set交给TaskScheduler
TaskScheduler:将DAGScheduler发送过来的task set 中的task分配给注册的Excutor上运行
stage:一个spark作业包含一到多个stage
task:几个分区就几个task,可以并行运行
RDD
RDD的概念
1、RDD是一个弹性的分布式数据集,是Spark中的基本抽象,表示可以并行操作的可分区的,不可变的,元素的集合。
2、RDD的弹性是指:
自动进行内存和磁盘的切换
基于血统的高效容错机制(假如一个RDD失败了,可以通过重新计算上一个RDD来重新生成丢失的数据)
失败之后的自动重试(默认为4次);可以通过persist方法将RDD的数据存在内存或者磁盘上,当再次使用到的时候直接读取就行(也可以执行checkpoint机制,检查点会将数据存储在hdfs上,当执行检查点机制之后,会将所有的父依赖全部移除)
数据分片的高度弹性(可以根据业务的特征,动态调整数据分片的个数,提升整体的运行速度)
在spark
3、RDD的分区:一个RDD中有多个分区,分区可以根据业务需求来指定
4、RDD的不可变:RDD一旦被创建,指向的数据是只读的,如果想要修改数据,只能调用算子来计算后产生一个新的RDD
5、RDD的并行:有多个分区,多个task,可以并行运算
6、RDD允许用户在执行多个查询时显式的将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度
7、RDD具有数据流模型的特点:自动容错,位置感知性调度和可伸缩性
RDD不会存储真正的数据,而是通过分区里的索引信息指向真正的数据
RDD的结构
每个 RDD 里都会包括分区信息、依赖关系等等的信息,如下图所示:
1)分区(Partitions)
- 一个RDD中可能包含多个分区。好比RDD是一个数组,分区是一个元素。
- 分区不会真正的存储数据。而是存储数据的索引index.指向一个存储在内存或者硬盘中的数据块 (Block)
注意:RDD对应的数据尽可能的使用内存,只有内存不够用的时候才会存在磁盘上
- SparkContext
SparkContext 是所有 Spark 功能的入口,代表了与 Spark 节点的连接,可以用来创建 RDD 对象以及在节点中的广播变量等等。一个线程只有一个 SparkContext。
3)SparkConf
SparkConf 是一些配置信息。
4)Partitioner
Partitioner 决定了 RDD 的分区方式,目前两种主流的分区方式:Hash partioner 和 Range partitioner。Hash 就是对数据的 Key 进行散列分布,Range是按照 Key 的排序进行的分区。也可以自定义 Partitioner。
5)Dependencies
Dependencies 也就是依赖关系,记录了该 RDD 的计算过程,也就是说这个 RDD 是通过哪个 RDD 经过怎么样的转化操作得到的。
这里有个概念,根据每个 RDD 的分区计算后生成的新的 RDD 的分区的对应关系,可以分成窄依赖和宽依赖。
- 窄依赖就是父 RDD 的分区可以一一对应到子 RDD 的分区,
- 宽依赖是说父 RDD 的每个分区可以被多个子 RDD 分区使用。
如图:
由于窄依赖的特性,窄依赖允许子 RDD 的每个分区可以被并行处理产生,而且支持在同一个节点上链式执行多条指令,无需等待其它父 RDD 的分区操作。
Spark 区分宽窄依赖的原因主要有两点:
-
窄依赖支持在同一节点上进行链式操作,比如在执行了 map 后,紧接着执行 filter 操作。相反,宽依赖需要所有父分区都是可用的。
-
从失败恢复的角度考虑,窄依赖失败恢复更有效,因为只要重新计算丢失的父分区即可,而宽依赖涉及到 RDD 的各级多个父分区。
6)Checkpoint
检查点机制,在计算过程中有一些比较耗时的 RDD,我们可以将它缓存到硬盘或者 HDFS 中,标记这个 RDD 有被检查点处理过,并且清空它的所有依赖关系。同时,给它新建一个依赖于 CheckpointRDD 的依赖关系,CheckpintRDD 可以用来从 硬盘中读取 RDD 和生成新的分区信息。
这么做之后,当某个 RDD 需要错误恢复时,回溯到该 RDD,发现它被检查点记录过,就可以直接去硬盘读取该 RDD,无需重新计算。
7)Preferred Location
针对每一个分片,都会选择一个最优的位置来计算,数据不动,代码动。
8)Storage Level
用来记录 RDD 持久化时存储的级别,常用的有:
-
MEMORY_ONLY:只存在缓存中,如果内存不够,则不缓存剩余的部分。这是 RDD 默认的存储级别。
-
MEMORY_AND_DISK:缓存在内存中,不够则缓存至磁盘。
-
DISK_ONLY:只存硬盘。
-
MEMORY_ONLY_2 和 MEMORY_AND_DISK_2等:与上面的级别和功能相同,只不过每个分区在集群两个节点上建立副本。
9)Iterator
迭代函数和计算函数是用来表示 RDD 怎样通过父 RDD 计算得到的。
迭代函数首先会判断缓存中是否有想要计算的 RDD,如果有就直接读取,如果没有就查找想要计算的 RDD 是否被检查点处理过。如果有,就直接读取,如果没有,就调用计算函数向上递归,查找父 RDD 进行计算。