概述
本文讲述如何使用checkpoint来保存rdd,并读取还原rdd的数据。
checkpoint简介
checkpoint可以把rdd持久化到磁盘上,可以是本地磁盘也可以是外部存储系统(比如:hadoop文件系统)。
要注意的是:在rdd进行checkpoint时,会先把rdd的血缘(lineage)去掉。
另外:在大数据量的情况下,保存和读取rdd数据也会十分消耗资源。所以,是选择使用checkpoint机制来还原数据,还是重新计算该rdd,在实际的场景中还需要权衡。
如何保存和读入checkpoint的数据
- 通过checkpoint保存rdd的方法
在保存rdd数据时首先要指定一个外部存储的目录,指定目录的函数为:
sc.setCheckpointDir
- 读取checkpoint的rdd
读取checkpoint的rdd时需要知道rdd存储的路径。在SparkContext中有一个函数可以直接读取checkpoint目录中的数据,该函数的定义如下:
protected[spark] def checkpointFile[T: ClassTag](path: String): RDD[T] = withScope {
new ReliableCheckpointRDD[T](this, path)
}
可知该函数会返回一个ReliableCheckpointRDD。但该函数是protected的,不能通过sparkContext直接调用。
我们知道protected函数的权限是包范围内或子类,所以我们需要定义一个类,该类需要在和SparkContext相同的包内,也就是在包:package org.apache.spark中。
checkpoint实战
通过checkpoint持久化保存rdd数据
启动spark-shell,并输入以下命令:
sc.setCheckpointDir("hdfs://hadoop3:7078/data/checkpoint")
val rdd1 = sc.parallelize(Array((1,2),(3,4),(5,6),(7,8)),3)
rdd1.checkpoint()
//注意:要action才能触发checkpoint
rdd1.take(1)
通过以上几行代码,就把rdd保存到hdfs的data/checkpoint目录下了。
创建读取checkpoint的工具类
SparkContext中有一个checkpointFile方法可以直接读取
把下面的程序打成jar包,比如叫:dospark.jar
package org.apache.spark
import org.apache.spark.rdd.RDD
object RDDUtilsInSpark {
def getCheckpointRDD[T](sc:SparkContext, path:String) = {
//path要到part-000000的父目录
val result : RDD[Any] = sc.checkpointFile(path)
result.asInstanceOf[T]
}
}
//val checkpointPath="hdfs://hadoop3:7078/data/checkpoint"
//val rdd2 : RDD[Any] = sc.checkpointFile(checkpointPath)
注意:写入rdd数据时,会生成一些临时目录,而rdd是保存在这些临时目录的rdd-0,rdd-1这些目录下。
读取checkpoint的rdd数据时,需要把目录指定到最底层目录。
checkpoint后的目录如下:
ubuntu@vm10-210-1-16:~$ hadoop fs -lsr /data/checkpoint/
lsr: DEPRECATED: Please use 'ls -R' instead.
drwxr-xr-x - ubuntu supergroup 0 2019-04-16 17:22 /data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022
drwxr-xr-x - ubuntu supergroup 0 2019-04-16 17:22 /data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022/rdd-0
-rw-r--r-- 3 ubuntu supergroup 10 2019-04-16 17:22 /data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022/rdd-0/part-00000
-rw-r--r-- 3 ubuntu supergroup 10 2019-04-16 17:22 /data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022/rdd-0/part-00001
-rw-r--r-- 3 ubuntu supergroup 20 2019-04-16 17:22 /data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022/rdd-0/part-00002
drwxr-xr-x - ubuntu supergroup 0 2019-04-16 17:22 /data/checkpoint/ece299b9-b352-4138-8ee6-44dcdcb5eed6
读取时需要要指定到rdd-0这一层的目录才能读取数据。
使用工具类读取checkpoint的数据
这里讲述如何在spark-shell中来读取checkpoit的数据,步骤如下:
- 启动spark-shell时,加上dospark.jar这个包:
spark-shell --jars dospark.jar
- 使用:
import org.apache.spark.rdd.RDD
import org.apache.spark.RDDUtilsInSpark
val checkpointPath="hdfs://hadoop3:7078/data/checkpoint/7d020f7b-9122-4247-ba2d-80b8277a1022/rdd-0"
val rdd : RDD[(Int, Int)]= RDDUtilsInSpark.getCheckpointRDD(sc, checkpointPath)
println(rdd.count())
rdd.collect().foreach(println)
总结
本文讲述了如何通过spark的checkpoint把rdd数据保存到外部分布式文件系统中。再通过SparkContext的checkpointFile函数读取rdd数据并还原。
要注意的是:在大数据量的情况下,保存和读取rdd数据也会十分消耗资源。
所以,是使用checkpoint机制来还原数据,还是重新计算该rdd,在实际的场景中还需要权衡。