RDD持久化
在Spark中,最重要的能力之一就是持久化一个数据集到内存中。当你持久化一个RDD时,每个节点存储这个RDD的所有分区,它在内存中计算,其他对該数据集(或者由它衍生的数据集)的行动可以重用他们。这就使得后续行动能够变得更加快速(通常超过10倍)。Caching是一个用于迭代算法和快速交互的key工具。
你可以使用persist()
或cache()
方法标记一个RDD被持久化,首次计算发生在一个行动中,它将保存在节点的内存中。Spark的缓存是容错的--如果一个RDD的任何不念旧恶分区丢失了,它将使用原来创建它的转换来自动重新计算。
另外,每个持久化的RDD能够允许你使用不同的存储级别被存储,例如,持久化数据集到磁盘,作为序列化的Java对象持久化到内存,并在各个节点复制它。这些级别通过传递一个StorageLevel object (Scala, Java, Python)给persist()
来设置。cache()
方法比较容易,它使用默认的存储级别,这个级别是StorageLevel.MEMORY_ONLY(存储序列化对象在内存)。全部的存储级别集合有:
存储级别 | 含义 |
---|---|
MEMORY_ONLY | 存储RDD作为一个序列化的Java对象到JVM中。如果RDD不能放到内存,一些分区将不能被缓存,在每次需要他们的时候,这些分区将会被快速重新计算,这是默认的存储级别。 |
MEMORY_AND_DISK | 存储RDD作为一个序列化的Java对象到JVM中。如果RDD不能放到内存,存储这些不能放入内存的分区到磁盘,在需要时候再读取他们。 |
MEMORY_ONLY_SER (Java and Scala) | 存储RDD作为一个序列化的Java对象(每个分区用一个字节数组)。这通常比序列化对象更节省空间,尤其是使用一个快速的序列器,但是读的时候对CPU更敏感。 |
MEMORY_AND_DISK_SER (Java and Scala) | 与MEMORY_ONLY_SER类似,但是溢写那些不能放入内存的分区到磁盘,而不是在每次需要的时候进行快速的重新计算。 |
DISK_ONLY | 只存储RDD分区到磁盘 |
MEMORY_ONLY_2, MEMORY_AND_DISK_2, etc. | 存储级别与上面相同,但是每个分区的副本在两个集群中的节点中。 |
OFF_HEAP (experimental) | 与MEMORY_ONLY_SER类似,但是存储数据在off-heap内存中,这要求off-heap内存被启用。 |
注意:在Python中,存储对象将一直被Pickle庫序列化,因此,你是否选择一个序列化级别是没有关系的。在Python中可用的存储级别包括: MEMORY_ONLY, MEMORY_ONLY_2, MEMORY_AND_DISK, MEMORY_AND_DISK_2, DISK_ONLY, 和 DISK_ONLY_2.
Spark也会自动持久化一些在混洗操作(例如reduceByKey)产生的中间数据,甚至不需用户调用persist。这样做是为了,如果一个节点在混洗期间失败,避免重新计算整个输入.如果打算重新使用产生的RDD,我们仍然推荐用户調用persist,来持久化那些RDD。