Spark RDD 持久化

来源:互联网 发布:mac os支持office 2016 编辑:程序博客网 时间:2024/06/05 00:09

Spark RDD 持久化

注:该文档针对Spark2.1.0版本

Spark最重要的一个功能是它可以通过各种操作(operations)持久化(或者缓存)一个集合到内存中。当你持久化一个RDD的时候,每一个节点都将参与计算的所有分区数据存储到内存中,并且这些数据可以被这个集合(以及这个集合衍生的其他集合)的动作(action)重复利用。这个能力使后续的动作速度更快(通常快10倍以上)。对应迭代算法和快速的交互使用来说,缓存是一个关键的工具。

你能通过persist()或者cache()方法持久化一个rdd。首先,在action中计算得到rdd;然后,将其保存在每个节点的内存中。Spark的缓存是一个容错的技术-如果RDD的任何一个分区丢失,它可以通过原有的转换(transformations)操作自动的重复计算并且创建出这个分区。

此外,每个持久化的RDD可以使用不同的存储级别存储,例如,允许您在磁盘上持久化数据集,将其保存在内存中,但作为序列化的Java对象(为了节省空间),可以跨节点复制它。这些级别通过传递一个StorageLevel对象(Scala、Java、Python)来持久化()。cache()方法是使用默认存储级别的缩写,它是StorageLevel。MEMORY_ONLY(存储在内存中的反序列化对象)。完整的存储级别为:

存储级别 解释 MEMORY_ONLY 将RDD作为非序列化的Java对象存储在jvm中。如果RDD不适合存在内存中,一些分区将不会被缓存,从而在每次需要这些分区时都需重新计算它们。这是系统默认的存储级别。 MEMORY_AND_DISK 以反序列化的JAVA对象的方式存储在JVM中. 如果内存不够, RDD的一些分区将将会缓存在磁盘上,再次需要的时候从磁盘读取 MEMORY_ONLY_SER 以序列化JAVA对象的方式存储 (每个分区一个字节数组). 相比于反序列化的方式,这样更高效的利用空间, 尤其是使用快速序列化时。但是读取是CPU操作很密集。 MEMORY_AND_DISK_SER 与MEMORY_ONLY_SER相似, 区别是但内存不足时,存储在磁盘上而不是每次重新计算 DISK_ONLY 只存储RDD在磁盘 MEMORY_ONLY_2, MEMORY_AND_DISK_2, etc. 与上面的级别相同,只不过每个分区的副本只存储在两个集群节点上。 OFF_HEAP (experimental) 与MEMORY_ONLY_SER类似,但将数据存储在非堆内存中。这需要启用非堆内存。

:在python里,通过Pickle库来存储对象总是以序列化的方式,与存储级别中的序列化标志无关。

Spark也自动地持久化一些中间数据在shuffle操作中,尽管用户没有调用persist.这样做是为了避免重新计算整个输入当一个节点失败时。我们建议用户对结果RDD调用persist,如果计划重复使用它们。

存储级别的选择

Spark的存储级别是为了提供内存使用率和CPU效率的均衡。我们建议您通过以下方式来选择:

  1. 如果你的RDD在默认的存储级别下工作的很好,就不要用其它的级别。这是最有CPU效率的选项,允许RDD上的操作尽快的完成。
  2. 如果不行,试下MEMORY_ONLY_SER并使用一个能快速序列化的库,这样更节省空间,同时访问速度也比较快。
  3. 不要存储数据到磁盘,除非在数据集上的计算操作是昂贵的,或者过滤了大量的数据。否则重新计算可能比从磁盘中读取更快
  4. 使用备份级别,如果你需要更快的恢复。(比如,使用Spark为网络应用程序提供服务)。所有的存储级别都通过重新计算提供了全面的容错性,但是备份级别允许你继续在RDD上执行任务而无需重新计算丢失的分区。

移除持久化

Spark自动地监控每个节点上的缓存使用率。并通过LRU算法删除过时的数据。如果你想手动删除一个RDD而不是等待它从缓存中过时,可以使用RDD.unpersist方法。

参考文档

http://spark.apache.org/docs/2.1.0/programming-guide.html#rdd-persistence

原创粉丝点击