希望多多指导,qq 86497564 。

© 天行自息
Powered by LOFTER

SparkRdd持久化(缓存)

RDD 持久化原理:

    (1)Spark 非常重要的一个功能特性就是可以将 RDD 持久化在内存中。当对 RDD 执行持久化操作时,每个节点都会将自己操作的 RDD 的 partition 持久化到内存中,并且在之后对该 RDD 的反复使用中,直接使用内存缓存的 partition。这样的话,对于针对一个 RDD 反复执行多个操作的场景,就只要对 RDD 计算一次即可,后面直接使用该 RDD,而不需要反复计算多次该 RDD。巧妙使用 RDD持久化,甚至在某些场景下,可以将 spark 应用程序的性能提升 10 倍。对于迭代式算法和快速交互式应用来说,RDD 持久化,是非常重要的。

    (2)要持久化一个 RDD,只要调用其 cache()或者 persist()方法即可。在该RDD 第一次被计算出来时,就会直接缓存在每个节点中。而且 Spark 的持久化机制还是自动容错的,如果持久化的 RDD 的任何 partition 丢失了,那么 Spark 会自动通过其源 RDD,使用 transformation 操作重新计算该 partition。

    (3)cache()和 persist()的区别在于,cache()是 persist()的一种简化方式,cache() 的底层就是调用的 persist() 的无参版本,同时就是调用persist(MEMORY_ONLY),将数据持久化到内存中。如果需要从内存中清除缓存,那么可以使用 unpersist()方法。

    (4)Spark 自己也会在 shuffle 操作时,进行数据的持久化,比如写入磁盘,主要是为了在节点失败时,避免需要重新计算整个过程。

    RDD 持久化策略:RDD 持久化是可以手动选择不同的策略的。比如可以将RDD 持久化在内存中、持久化到磁盘上、使用序列化的方式持久化,多持久化的数据进行多路复用。只要在调用 persist()时传入对应的 StorageLevel(这是一个枚举类型)即可。

    持久化级别:

    MEMORY_ONLY(默认):以非序列化的 Java 对象的方式持久化在 JVM 内存中。如果内存无法完全存储 RDD 所有的 partition,那么那些没有持久化的partition 就会在下一次需要使用它的时候,重新被计算。

    MEMORY_AND_DISK:同上,但是当某些 partition 无法存储在内存中时,会持久化到磁盘中。下次需要使用这些 partition 时,需要从磁盘上读取。

    MEMORY_ONLY_SER:同 MEMORY_ONLY,但是会使用 Java 序列化方式,将Java 对象序列化后进行持久化。可以减少内存开销,但是需要进行反序列化,因此会加大 CPU 开销。

    MEMORY_AND_DSK_SER:同 MEMORY_AND_DSK。但是使用序列化方式持久化 Java 对象。

    DISK_ONLY:使用非序列化 Java 对象的方式持久化,完全存储到磁盘上。

    MEMORY_ONLY_2、MEMORY_AND_DISK_2 等等:如果是尾部加了 2 的持久化级别,表示会将持久化数据复用一份,保存到其他节点,从而在数据丢失时,不需要再次计算,只需要使用备份数据即可。

    如何选择 RDD 持久化策略:Spark 提供的多种持久化级别,主要是为了在CPU 和内存消耗之间进行取舍。下面是一些通用的持久化级别的选择建议:

    (1)优先使用 MEMORY_ONLY,如果可以缓存所有数据的话,那么就使用这种策略。因为纯内存速度最快,而且没有序列化,不需要消耗 CPU 进行反序列化操作。

    (2)如果 MEMORY_ONLY 策略,无法存储的下所有数据的话,那么使用MEMORY_ONLY_SER,将数据进行序列化进行存储,纯内存操作还是非常快,只是要消耗 CPU 进行反序列化。

    (3)如果需要进行快速的失败恢复,那么就选择带后缀为_2 的策略,进行数据的备份,这样在失败时,就不需要重新计算了。

    (4)能不使用 DISK 相关的策略,就不用使用,有的时候,从磁盘读取数据,还不如重新计算一次。

评论
热度 ( 1 )