本文共 1718 字,大约阅读时间需要 5 分钟。
1、RDD的缓存
Spark速度快的原因之一,不同操作中在内存中持久化个RDD。每个节点都把计算的分区结果保存在内存中,并在对此RDD重用
2、RDD缓存方式
RDD通过persist方法(或cache方法,最终也是调用了persist方法)将前面计算结果以序列化的形式缓存在 JVM的堆空间中。但并不是调用立即缓存,而是触发action时,RDD会被缓存在计算节点的内存中,供重用
默认存储级别都是仅在内存存储一份,存储级别可在object StorageLevel中定义
RDD的缓存容错机制保证了即使缓存丢失也能保证计算的正确执行。各个Partition相对独立,因此只需要计算丢失的部分,不需要重算全部Partition
1、检查点(本质将RDD写入Disk做检查点)是为了通过Lineage(血统)做容错的辅助
Lineage过长会造成容错成本过高,不如在中间阶段做检查容错,如果有节点出现问题丢失分区,从做检查点的RDD开始重做Lineage,减少开销。检查点将数据写入到HDFS文件系统
2、Lineage(血统):记录RDD的元数据信息和转换行为,当RDD部分分区数据丢失时,可根据这些信息来恢复丢失的数据分区
3、Cache 和 CheckPoint 的区别
缓存把 RDD结果放在内存中,但RDD依赖链不能丢掉,当某个点某个executor宕了,缓存的RDD丢失,需要通过依赖链重放计算
CheckPoint把RDD保存在 HDFS中,多副本可靠存储,依赖链丢掉,通过复制实现高容错
4、应用场景
1)DAG中的Lineage过长
2)在宽依赖上做检查点获得收益更大
RDD是粗粒度的数据集,每个Transformation操作都会生成一个新的RDD,所以RDD之间就会形成前后依赖关系,RDD和它依赖的父RDD有两种不同的关系类型,即窄依赖和宽依赖
窄依赖:每一个父RDD的Partition最多被子RDD的一个Partition使用
宽依赖:多个子RDD的Partition会依赖同一个父RDD的Partition,会引起shuffle
DAG有向无环图,原始的RDD通过一系列转换形成了DAG,根据RDD之间依赖关系不同将DAG划分成不同的Stage,窄依赖,partition的转换处理在Stage中完成计算。宽依赖,因为Shuffle,只有parent RDD完成后,才能开始计算,因此宽依赖是划分Stage的依据
输入文件存储在HDFS上,每个File都包含了很多块,称为Block
Spark读取文件作为输入,根据数据格式对应的InputFormat进行解析,将若干个Block合并成一个输入分区(InputSplit)
输入分区生成Task(InputSplit与Task一 一对应)
Task被分配到集群上的某个节点的某个Executor执行
Task数目
- 节点可以有多个Executor
- Executor由若干core(Executor的一个工作线程)组成,每个core一次只能执行一个Task
- Task执行结果就是生成了RDD的一个partiton
Task并发度 = Executor * Executor核数
Partition数目
- 数据读入阶段,输入文件被划分为多少InputSplit就产生多少初始Task
- Map阶段partition数目保持不变
- Reduce阶段,RDD的聚合触发shuffle操作,聚合后的RDD的partition数目跟具体操作有关
Spark调优
资源配置为十个计算节点,每个两个Core,同一时刻可以并行的Task数目为20,比如RDD有100个分区,那么计算的时候就会生成100个Task,计算这个RDD就需要5个轮次。如果计算资源不变,有101个Task,就需要6个轮次,最后一轮中,只有一个Task在执行,其余核都在空转。如果资源不变,RDD只有2个分区,那么同一时刻只有2个Task运行,其余18个核空转,造成资源浪费
增大RDD分区数目,调整任务并行度,达到调优目的
转载地址:http://bvazi.baihongyu.com/