Spark2.2-persist checkpoint lineage解析
来源:互联网 发布:js打印当前时间 编辑:程序博客网 时间:2024/06/10 11:55
源码版本: 2.2
一、背景
二、Checkpoint
2.1 checkpoint写
2.2 checkpoint读
三、Persist
3.1 persist写
persist操作过程中,首先会在Dataset调用cacheManager来注册一个缓存的Dataset,注意,cache不会影响RDD的正常计算流程,即action操作才会触发job的提交和计算。所以在这里注册时是根据Dataset的逻辑执行计划来注册的。
和RDD的cache默认使用内存不一样,Dataset的cache默认存储级别是DISK,因为重新计算底层表的内存列式数据代价较大。
() => { readCachedBlock = false computeOrReadCheckpoint(partition, context)}
这个函数中直接调用了computeOrReadCheckpoint去对RDD进行计算,返回计算完成的结果
很长的一个方法,我这里只说说几个比较重要的地方。这个方法顾名思义是用来缓存数据的,那么在执行缓存之前需要做一些准备工作。首先通过一个match确定是否要返回数据以及选择一个什么类型的BlockStore。对于BlockStore这里分了三种:memoryStore、tachyonStore、diskStore。第一种和第三种每什么疑问,至于tachyon是一个内存分布式文件系统,建立在ramdisk之上,和spark同宗同源,是spark兼容的存储系统之一,可以用来不同application之间共享rdd甚至与其他例如storm这样的框架共享内存数据,不过目前貌似还是在实验阶段,官网上有标注的。
3.2 persist读
persist读操作其实在写操作是耦合的,执行写操作之前都会先执行一次读操作,确认没有才会执行写。读操作同样也在RDD进行iterator迭代时调用的getOrCompute方法中
RDD根据它自身的id和分区partition的下标构造一个blockid,向blockManager请求,如果获取到请求结果,则直接返回,如果没有获取到,则会先对RDD进行计算,写入BlockManager,同时返回。
但是为什么在persist写操作的时候是根据Dataset的logicalPlan构造一个CacheData放入SparkSession间接维护的CacheManager中,而读的时候却是请求的BlockManager呢?
因为CacheManager的作用并不是为了管理cache流程,CacheManager存储Dataset的logicalPlan,是为了支持SQLContext中的数据缓存功能,支持根据Dataset或是logicalPlan进行缓存数据的搜索。实际上缓存数据的存储还是由BlockManager进行管理的。
四、Lineage
Spark的RDD对象中记录了它的血统Lineage,RDD的Lineage记录的是粗颗粒度的特定数据Transformation操作(如filter、map、join等)行为。
4.1 Lineage切入点:toDebugString
在本地debug时,Spark提供了一种查看RDD Lineage的操作toDebugString。
Spark在生成RDD的具体血缘关系时,对RDD的依赖进行迭代遍历,遍历时通过提供的几个方法就可以窥探出RDD Lineage的大概结构。
- debugSelf
- debugChildren
- firstDebugString
- shuffleDebugString
- debugString
4.2 RDD的Dependency
关于dependency,RDD中维护了两个变量,一个是构造函数参数deps
另一个是private变量dependencies_
从本质上来说,实际对RDD的Lineage有用的数据结构是Dependency。Dependency抽象类中维护了对应被依赖的RDD的引用,同时根据依赖特性,分为两大类NarrowDependency和ShuffleDependency,NarrowDependency又细分为三种类型OneToOneDependency、PruneDependency和RangeDependency,分别根据依赖特性实现了自己的getParent以及一些其他辅助方法。
这两个变量其实都是指向RDD的依赖关系,RDD提供了从deps赋值到dependencies_的转换函数。这个转换函数会将RDD的构造参数deps赋值给private成员变量dependencies_,为什么要增加一道转换操作而不直接使用呢,从下面这个函数里看出,是为了做checkpoint的lineage切断。当RDD做过checkpoint后,它的checkpointRDD成员变量会存放一个由它自身数据构造的一个CheckpointRDD,此时再去获取这个RDD的dependency时,RDD会用这个CheckpointRDD去new一个新的OneToOneDependency,也就是它自身的依赖只有它自己的Checkpoint RDD了,以此来达到切断Lineage的作用。所有对RDD依赖关系访问的操作都是直接调用dependencies方法,而不是调用RDD自身的dependency成员变量。
针对上一个问题,可能大家会产生疑问,针对CheckPoint切断Lineage的目的是什么?我们可以首先看一下Lineage信息在RDD计算中的作用。
首先,每一个RDD在进行数据计算时,都调用了RDD的iterator来对数据进行迭代访问。在进行迭代访问时,假设RDD没有进行cache和checkpoint,那么RDD就会使用到它的Lineage进行计算。
实际的计算过程在RDD的compute方法中,针对不同类型的RDD实现类,有不同的实现方法。例如,针对从数据源转化而来的RDD或是Checkpoint,它们的compute方法可能是读取文件,而其他类型的RDD中的compute可能会在数据上执行一些函数。
在这里,我们抽取集中比较典型的RDD进行分析,跟踪Lineage信息在计算过程中的真正作用。
- MapPartitionsRDD
MapPartitionsRDD这个会将它的函数作用于它的父RDD中的每一个partition。 在它的compute中,我们可以看到,它在apply函数f时首先会调用firstParent[T].iterator(split, context),即先去触发它的parent的计算。
获取一个RDD的firstParent的方法如下,获取自身的Dependency的头节点,即parent,获取该Dependency的RDD提交计算。
这样,RDD在计算过程中就可以根据它的Lineage去恢复整个计算流程了。
4.3 Lineage小结
Spark的数据Lineage记录了数据集之间的依赖以及操作流程,其中,数据集的依赖关系实例化存放在每一个基础数据对象RDD中,每个RDD维护它自己的计算方式。这两者结合起来实现了完整的Data Lineage。
- Spark2.2-persist checkpoint lineage解析
- spark2.2内核剖析---checkpoint与presist
- spark2.0原理分析--RDD Lineage(逻辑执行计划)
- 【总结】论spark中的cache/persist/checkpoint
- Spark2.2-Task序列化源码解析
- spark中的cache() persist() checkpoint()之间的区别
- spark中的cache() persist() checkpoint()之间的区别
- QTP检查点CheckPoint解析
- [spark] Checkpoint 源码解析
- 0002.spark2.0源码解析(2)--master的HA
- Spark2.2任务提交运行机制及源码解析
- Spark2.2 Task原理分析及源码解析
- Checkpoint和SCN的解析
- Checkpoint和SCN的解析
- Checkpoint和SCN的解析
- checkpoint
- CheckPoint
- checkpoint
- MapReduce编程案例——数据去重
- 处理运行时变更,activity被销毁后的重建,常见于屏幕旋转
- Android 设备兼容性使用方法详解
- Android rxjava用法浅析
- 【测试】Fiddler实现手机抓包
- Spark2.2-persist checkpoint lineage解析
- 1.4.6 霍夫曼编码(Huffman Coding)
- 客户端开发注意事项
- Unconstrained Face Alignment via Cascaded Compositional Learning
- 内联函数和宏定义
- Android动态设置宽高
- saltstack_install
- TI BLE CC2541 Notification
- Windows+Python3.6.0(Anaconda3)+OpenCV3.2.0安装配置