Ch07-Spark 之缓存
May 31, 2019
Spark 的一个重要特性是能够把计算结果数据保存到内存或磁盘中,供后面的操作读取,这就是 RDD 的缓存,这个过程也可称为 persist 或 caching(Spark 提供了 persist()
和 cache()
函数来缓存 RDD)。
1. persist #
persist()
函数只是对 RDD 的 storageLevel(存储级别)进行了设置,函数内部并没有执行任何数据缓存的动作。
- 在通过 RDD 的 iterator 读取 RDD 分区数据时,判断 RDD 的 storageLevel 变量,若该变量的值不是默认值 StorageLevel.NONE,则说明 storageLevel 的值已经被 persist 函数配置过。进入第 2 步。
- storageLevel 不为 StorageLevel.NONE,则首先从内存或磁盘中获取数据,此时会调用 BlockManager#get 函数根据 storageLevel 从内存或磁盘中获取数据块。若获取到了数据块则直接返回。没有从内存或磁盘获取到数据块,则需要计算数据块,进入第 3 步。
- 若从内存或磁盘中没有获取到数据,则需要计算该数据。计算完成后,会根据存储级别(storageLevel 的值)把计算出来的分区数据保存到内存或磁盘中,供下一次读取。
1.1 StorageLevel #
持久化级别 | 说明 |
---|---|
MEMORY_ONLY | 将 RDD 存储为 JVM 中的反序列化 Java 对象。如果 RDD 不存在内存时,则某些分区将不会被缓存,并且每次需要时都会重新计算。 |
MEMORY_AND_DISK | 将 RDD 存储为 JVM 中的反序列化 Java 对象。如果 RDD 不适合保存在内存中,则可以保存在磁盘中,需要时可以从磁盘读取。 |
MEMORY_ONLY_SER | 将 RDD 存储为 JVM 中的序列化 Java 对象。通常比反序列化对象更节省空间,特别是在使用快速序列化器时,但是读取 CPU 密集程度更高。 |
MEMORY_AND_DISK_SER | 与 MEMORY_ONLY_SER 类似,但会将不适合内存的分区溢出到磁盘。而不是每次需要时在实时计算它们。 |
DISK_ONLY | 仅将 RDD 分区存储在磁盘上。 |
MEMORY_ONLY_2MEMORY_AND_DISK_2 | 将 RDD 在其他节点上再保存一份,在数据丢失时,不需要再次计算。 |
OFF_HEAP | RDD 存储在对外内存中。 |
2. cache #
def cache(): this.type = persist()