前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住给大家分享一下。点击跳转到网站:https://www.captainai.net/dongkelun
前言
总结一下Spark Checkpoint 用法及源码,包括RDD和Spark Streaming两种。
1、RDD
作用:持久化数据-将RDD的数据保存到可靠文件系统中(一般是HDFS),以便数据恢复
容错、复用:在Spark程序中,如果某个RDD因为业务逻辑比较复杂,导致Transformation很多,计算很耗时,且该RDD后面用到很多次,那么有可能因为各种原因导致数据丢失、程序失败,之后Spark会重新尝试执行程序(默认三次),就需要重新从头开始执行,而如果执行了Checkpoint,那么就会直接从HDFS文件读取相关数据信息,不需要从头开始执行,节省很多时间。
cache和persist:有了cache和persist,还需要Checkpoint么?需要,因为cache到内存,虽然最快,但是也最不可靠,即使persist到磁盘也不如HDFS文件系统可靠,且能cache到内存最好在内存,因为这样很快,然后和Checkpoint一起用,就能既保证了速度也保证了可靠性。
1.1 用法
代码示例
1 | //首先设置Checkpoint路径,这会在hdfs建立文件夹 |
1.2 源码
1.2.1 setCheckpointDir
建立对应的文件夹(fs.mkdirs(path))
1 | /** |
1.2.2 checkpoint
调用checkpoint,标记该RDD要Checkpoint,将checkpointData设为ReliableRDDCheckpointData,transformation操作,直到action操作才会执行,所以必须在一个action算子之前执行
1 | /** |
1.2.3 action算子
每个action算子都会调用sc.runJob方法,而runJob方法在最后会调用rdd.doCheckpoint()方法
1 | /** |
1.2.4 doCheckpoint
- rdd.doCheckpoint()=>checkpointData.get.checkpoint()
1 | /** |
- checkpointData.get.checkpoint()=>val newRDD = doCheckpoint()
cpState = CheckpointingInProgress,最开始cpState = Initialized(protected var cpState = Initialized)
1 | /** |
- 上面的checkpoint方法将checkpointData设为ReliableRDDCheckpointData,所以会调用ReliableRDDCheckpointData的doCheckpoint方法
在第一个action算子执行完之后,该方法会立即执行,将RDD的内容写到可靠的文件系统(ReliableCheckpointRDD.writeRDDToCheckpointDirectory)
doCheckpoint():
1 | /** |
1.2.5 writeRDDToCheckpointDirectory
可以看到这里会触发一个job
其中writePartitionToCheckpointFile是将分区数据写入checkpoint文件,writePartitionerToCheckpointDir是将分区写入checkpoint文件
1 | /** |
1.2.6 rdd.markCheckpointed()
在checkpointData.get.checkpoint()方法里可以看到最后会先将cpState = Checkpointed,然后执行rdd.markCheckpointed()
从检查点文件创建新的RDD,清除旧的依赖和分区
1 | /** |
1.2.7 读 checkpoint
当执行action算子时,会触发job,通过sc.runJob方法,将函数(action算子)以参数的形式提交job,接着划分stage、提交stage、提交task、执行task,最后在org.apache.spark.scheduler.ResultTask.runTask方法里会调用rdd.iterator来获取rdd分区数据
1 | override def runTask(context: TaskContext): U = { |
看一下rdd.iterator
1 | /** |
没有cache时调用computeOrReadCheckpoint
1 | /** |