Spark-Caching /Checkpointing

简介: 功能:cacheing和checkpointing这2种操作是都是用来防止rdd(弹性分布式数据集)每次被引用时被重复计算带来的时间和空间上不必要的损失。区别:Caching cache 机制保证了需要访问重复数据的应用(如迭代型算法和交互式应用)可以运行的更快。

功能:

cacheing和checkpointing这2种操作是都是用来防止rdd(弹性分布式数据集)每次被引用时被重复计算带来的时间和空间上不必要的损失。

区别:

Caching
cache 机制保证了需要访问重复数据的应用(如迭代型算法和交互式应用)可以运行的更快。有多种级别的持久化策略让开发者选择,使开发者能够对空间和计算成本进行权衡,同时能指定out of memory时对rdd的操作(缓存在内存或者磁盘,并且可以指定在内存不够的情况下按照FIFO的策略选取一部分block交换到磁盘来产生空余空间)。因此Spark不但可以对rdd重复计算还能在节点发生故障时重新计算丢失的分区。最后,被缓存的rdd存在于一个running的应用的生命周期内,如果这个应用终止了,那么缓存的rdd也会同时被删除。
Checkpointing
checkpointing把rdd存储到一个可靠的存储系统(例如HDFS,S3)。checkpoint一个rdd有点类似于Hadoop中把中间计算结果存储到磁盘,损失部分执行性能来获得更好的从运行过程中出现failures时recover的能力。因为rdd是checkpoint在外部的存储系统(磁盘,HDFS,S3等),所以checkpoint过的rdd能够被其他的应用重用。

caching和checkpointing的联系

由rdd的计算路径来了解caching和checkpointing的相互作用。 Spark engine的核心是DAGScheduler。它把一个spark job分解成由若干个stages组成的DAG。每一个shuffle或者result stage再分解成一个个在RDD的分区中独立运行的task。一个RDD的iterator方法是一个task访问基础数据分区的入口:

/**
* Internal method to this RDD; will read from cache if applicable, or otherwise compute it.
* This should ''not'' be called by users directly, but is available for implementors of custom
* subclasses of RDD.
*/
final def iterator(split: Partition, context: TaskContext): Iterator[T] = {
    if (storageLevel != StorageLevel.NONE) {
        getOrCompute(split, context)
    } else {
        computeOrReadCheckpoint(split, context)
    }
}

如果设置了存储级别,表明rdd可能被缓存,它首先尝试调用getOrCompute方法从block manager中得到分区。

/**
* Gets or computes an RDD partition. Used by RDD.iterator() when an RDD is cached.
*/
private[spark] def getOrCompute(partition: Partition, context: TaskContext): Iterator[T] = {
        val blockId = RDDBlockId(id, partition.index)
        var readCachedBlock = true
        // This method is called on executors, so we need call SparkEnv.get instead of sc.env.
        SparkEnv.get.blockManager.getOrElseUpdate(blockId, storageLevel, elementClassTag, () => {
        readCachedBlock = false
        computeOrReadCheckpoint(partition, context)
    }) match {
        case Left(blockResult) =>
        if (readCachedBlock) {
            val existingMetrics = context.taskMetrics().registerInputMetrics(blockResult.readMethod)
                existingMetrics.incBytesReadInternal(blockResult.bytes)
            new InterruptibleIterator[T](context, blockResult.data.asInstanceOf[Iterator[T]]) {
                override def next(): T = {
                            existingMetrics.incRecordsReadInternal(1)
                            delegate.next()
                }
            }
        } else {
            new InterruptibleIterator(context, blockResult.data.asInstanceOf[Iterator[T]])
        }
        case Right(iter) =>
            new InterruptibleIterator(context, iter.asInstanceOf[Iterator[T]])
        }
}
如果block manager中没有这个rdd的分区,那么它就去computeOrReadCheckpoint:
/**
* Compute an RDD partition or read it from a checkpoint if the RDD is checkpointing.
*/
private[spark] def computeOrReadCheckpoint(split: Partition, context: TaskContext): Iterator[T] =
{
    if (isCheckpointedAndMaterialized) {
        firstParent[T].iterator(split, context)
    } else {
        compute(split, context)
    }
}

=computeOrReadCheckpoint这个方法会从checkpoint中寻找对应的数据,如果rdd没有被checkpoint,那么就从当前计算的分区开始计算。
cache 机制是每计算出一个要 cache 的 partition 就直接将其 cache 到内存了。但是checkpoint 没有使用这种第一次计算得到就存储的方法,而是等到 job 结束后另外启动专门的 job 去完成 checkpoint 。也就是说需要 checkpoint 的 RDD 会被计算两次。
因此,在使用 rdd.checkpoint() 的时候,建议加上 rdd.cache(),这样第二次运行的 job 就不用再去计算该 rdd 了,直接读取 cache 写磁盘。其实 Spark 提供了 rdd.persist(StorageLevel.DISK_ONLY) 这样的方法,相当于 cache 到磁盘上,这样可以做到 rdd 第一次被计算得到时就存储到磁盘上,但这个 persist 和 checkpoint 有很多不同。前者虽然可以将 RDD 的 partition 持久化到磁盘,但该 partition 由 blockManager 管理。
一旦 driver program 执行结束,也就是 executor 所在进程 CoarseGrainedExecutorBackend stop,blockManager 也会 stop,被 cache 到磁盘上的 RDD 也会被清空(整个 blockManager 使用的 local 文件夹被删除)。
而 checkpoint 将 RDD 持久化到 HDFS 或本地文件夹,如果不被手动 remove 掉,是一直存在的,也就是说可以被下一个 driver program 使用,而 cached RDD 不能被其他 dirver program 使用。

总结

使用checkpoint*会消耗更多的时间在rdd的读写*上(因为要使用外部存储系统HDFS,S3,或者磁盘),但是Spark worker的一些failures不一定导致重新计算。
另一方面,caching的rdd 不会永久占用存储空间,但是重新计算在Spark worker出现一些failures的时候是必要的。
综上,这2个都是取决于开发者自己的角度结合业务场景来使用,一般情况下,综合计算任务的性能来进行2者的选择(大部分情况用cache就够了,如果感觉 job 可能会出错可以手动去 checkpoint 一些 critical 的 RDD)。

目录
相关文章
|
4月前
|
关系型数据库 MySQL
Authentication plugin ‘caching_sha2_password‘ cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2
Authentication plugin ‘caching_sha2_password‘ cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2
|
5月前
|
存储 缓存 分布式计算
【Spark】Spark Core Day04
【Spark】Spark Core Day04
33 1
|
7月前
|
存储 缓存 分布式计算
Spark-Core
Spark-Core
27 0
Spark-Core
|
分布式计算 Java Spark
Optimizing Spark job parameters
Optimizing Spark job parameters
74 0
Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
|
分布式计算 Spark
Spark - ReturnStatementInClosureException: Return statements aren‘t allowed in Spark closures
Spark 使用 RDD 调用 Filter 函数时,dirver 端卡住,报错 ReturnStatementInClosureException: Return statements aren't allowed in Spark closures,即闭包内无法使用 return 函数。
290 0
Spark - ReturnStatementInClosureException: Return statements aren‘t allowed in Spark closures
|
SQL 机器学习/深度学习 存储
Spark Core
Spark Core
197 0
|
关系型数据库 MySQL
MySQL 连接出现 Authentication plugin 'caching_sha2_password' cannot be loaded
MySQL 连接出现 Authentication plugin 'caching_sha2_password' cannot be loaded
204 0
|
消息中间件 大数据 测试技术
Apache Avro as a Built-in Data Source in Apache Spark 2.4
Apache Avro 是一种流行的数据序列化格式。它广泛用于 Apache Spark 和 Apache Hadoop 生态系统,尤其适用于基于 Kafka 的数据管道。从 Apache Spark 2.
|
NoSQL PHP Redis
WordPress Caching Solutions Part 1 – Performance Benchmarking and Installing Redis Object Caching
In previous tutorials I took you through the steps to set up a new server instance, then get your WordPress sites up and running, including transactional emails.
2388 0