Spark中RDD的持久化/缓存

Spark RDD的缓存

  • Spark速度非常快的原因之一,就是在不同操作中可以在内存中持久化或者缓存数据集。当持久化某个RDD后,每一个节点都将把计算分区结果保存在内存中,对此RDD或衍生出的RDD进行的其他动作中重用。这使得后续的动作变得更加迅速。RDD相关的持久化和缓存,是Spark最重要的特征之一。可以说,缓存是Spark构建迭代式算法和快速交互式查询的关键。
  • Spark RDD 是惰性求值的,而有时我们希望能多次使用同一个RDD。如果简单地对RDD 调用行动操作,Spark 每次都会重算RDD 以及它的所有依赖。这在迭代算法中消耗格外大,因为迭代算法常常会多次使用同一组数据。
    var input = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7))
    val result = input.map(x => x*x)
    println(result.count())//7
    println(result.collect().mkString(","))//1,4,9,16,25,36,49
  • 为了避免多次计算同一个RDD,可以让Spark 对数据进行持久化。当我们让Spark 持久化存储一个RDD 时,计算出RDD 的节点会分别保存它们所求出的分区数据。如果一个有持久化数据的节点发生故障,Spark 会在需要用到缓存的数据时重算丢失的数据分区。如果希望节点故障的情况不会拖累我们的执行速度,也可以把数据备份到多个节点上。
  • 出于不同的目的,我们可以为RDD 选择不同的持久化级别。在Scala,默认情况下persist() 会把数据以序列化的形式缓存在JVM 的堆空间中。在Python 中,我们会始终序列化要持久化存储的数据,所以持久化级别默认值就是以序列化后的对象存储在JVM 堆空间中。当我们把数据写到磁盘或者堆外存储上时,也总是使用序列化后的数据。

  RDD缓存方式

缓存级别

userDisk

是否使用磁盘

useMemory

是否使用内存

useOffHeap

是否使用堆外内存

deserialized

是否反序列化

replication

副本数

NONE

false

false

false

false

1

DISK_ONLY

true

false

false

false

1

DISK_ONLY_2

true

false

false

false

2

MEMORY_ONLY

false

true

false

true

1

MEMORY_ONLY_2

false

true

false

true

2

MEMORY_ONLY_SER

false

true

false

false

1

MEMORY_ONLY_SER_2

false

true

false

false

2

MEMORY_AND_DISK

true

true

false

true

1

MEMORY_AND_DISK

true

true

false

true

2

MEMORY_AND_DISK_SER

true

true

false

false

1

MEMORY_AND_DISK_SER_2

true

true

false

false

2

OFF_HEAP

true

true

true

false

1

总结

持久化级别

说明

MEMORY_ONLY(默认)

将RDD以非序列化的Java对象存储在JVM中。 如果没有足够的内存存储RDD,则某些分区将不会被缓存,每次需要时都会重新计算。 这是默认级别。

MEMORY_AND_DISK(开发中可以使用这个)

将RDD以非序列化的Java对象存储在JVM中。如果数据在内存中放不下,则溢写到磁盘上.需要时则会从磁盘上读取

MEMORY_ONLY_SER (Java and Scala)

将RDD以序列化的Java对象(每个分区一个字节数组)的方式存储.这通常比非序列化对象(deserialized objects)更具空间效率,特别是在使用快速序列化的情况下,但是这种方式读取数据会消耗更多的CPU。

MEMORY_AND_DISK_SER (Java and Scala)

与MEMORY_ONLY_SER类似,但如果数据在内存中放不下,则溢写到磁盘上,而不是每次需要重新计算它们。

DISK_ONLY

将RDD分区存储在磁盘上。

MEMORY_ONLY_2, MEMORY_AND_DISK_2等

与上面的储存级别相同,只不过将持久化数据存为两份,备份每个分区存储在两个集群节点上。

OFF_HEAP(实验中)

与MEMORY_ONLY_SER类似,但将数据存储在堆内存中。 (即不是直接存储在JVM内存中)

如:Tachyon-分布式内存存储系统、Alluxio - Open Source Memory Speed Virtual Distributed Storage

  • 总结

1.RDD持久化/缓存的目的是为了提高后续操作的速度

2.缓存的级别有很多,默认只存在内存中,开发中使用memory_and_disk

3.只有执行action操作的时候才会真正将RDD数据进行持久化/缓存

4.实际开发中如果某一个RDD后面频繁的被使用,那么就可以将该RDD进行持久化/缓存

最后,RDD 还有一个方法叫作unpersist(),调用该方法可以手动把持久化的RDD 从缓存中移除。

猜你喜欢

转载自blog.csdn.net/qq_38483094/article/details/98618273