Spark- RDD持久化
官方原文:
RDD Persistence
One of the most important capabilities in Spark is persisting (or caching) a dataset in memory across operations. When you persist an RDD, each node stores any partitions of it that it computes in memory and reuses them in other actions on that dataset (or datasets derived from it). This allows future actions to be much faster (often by more than 10x). Caching is a key tool for iterative algorithms and fast interactive use.
You can mark an RDD to be persisted using the persist()
or cache()
methods on it. The first time it is computed in an action, it will be kept in memory on the nodes. Spark’s cache is fault-tolerant – if any partition of an RDD is lost, it will automatically be recomputed using the transformations that originally created it.
In addition, each persisted RDD can be stored using a different storage level, allowing you, for example, to persist the dataset on disk, persist it in memory but as serialized Java objects (to save space), replicate it across nodes, or store it off-heap in Tachyon. These levels are set by passing aStorageLevel
object (Scala, Java, Python) to persist()
. The cache()
method is a shorthand for using the default storage level, which is StorageLevel.MEMORY_ONLY
(store deserialized objects in memory). The full set of storage levels is:
Storage Level | Meaning |
---|---|
MEMORY_ONLY | Store RDD as deserialized Java objects in the JVM. If the RDD does not fit in memory, some partitions will not be cached and will be recomputed on the fly each time they're needed. This is the default level. |
MEMORY_AND_DISK | Store RDD as deserialized Java objects in the JVM. If the RDD does not fit in memory, store the partitions that don't fit on disk, and read them from there when they're needed. |
MEMORY_ONLY_SER | Store RDD as serialized Java objects (one byte array per partition). This is generally more space-efficient than deserialized objects, especially when using a fast serializer, but more CPU-intensive to read. |
MEMORY_AND_DISK_SER | Similar to MEMORY_ONLY_SER, but spill partitions that don't fit in memory to disk instead of recomputing them on the fly each time they're needed. |
DISK_ONLY | Store the RDD partitions only on disk. |
MEMORY_ONLY_2, MEMORY_AND_DISK_2, etc. | Same as the levels above, but replicate each partition on two cluster nodes. |
OFF_HEAP (experimental) | Store RDD in serialized format in Tachyon. Compared to MEMORY_ONLY_SER, OFF_HEAP reduces garbage collection overhead and allows executors to be smaller and to share a pool of memory, making it attractive in environments with large heaps or multiple concurrent applications. Furthermore, as the RDDs reside in Tachyon, the crash of an executor does not lead to losing the in-memory cache. In this mode, the memory in Tachyon is discardable. Thus, Tachyon does not attempt to reconstruct a block that it evicts from memory. If you plan to use Tachyon as the off heap store, Spark is compatible with Tachyon out-of-the-box. Please refer to this page for the suggested version pairings. |
Note: In Python, stored objects will always be serialized with the Pickle library, so it does not matter whether you choose a serialized level.
Spark also automatically persists some intermediate data in shuffle operations (e.g. reduceByKey
), even without users calling persist
. This is done to avoid recomputing the entire input if a node fails during the shuffle. We still recommend users call persist
on the resulting RDD if they plan to reuse it.
Which Storage Level to Choose?
Spark’s storage levels are meant to provide different trade-offs between memory usage and CPU efficiency. We recommend going through the following process to select one:
If your RDDs fit comfortably with the default storage level (
MEMORY_ONLY
), leave them that way. This is the most CPU-efficient option, allowing operations on the RDDs to run as fast as possible.If not, try using
MEMORY_ONLY_SER
and selecting a fast serialization library to make the objects much more space-efficient, but still reasonably fast to access.Don’t spill to disk unless the functions that computed your datasets are expensive, or they filter a large amount of the data. Otherwise, recomputing a partition may be as fast as reading it from disk.
Use the replicated storage levels if you want fast fault recovery (e.g. if using Spark to serve requests from a web application). All the storage levels provide full fault tolerance by recomputing lost data, but the replicated ones let you continue running tasks on the RDD without waiting to recompute a lost partition.
In environments with high amounts of memory or multiple applications, the experimental
OFF_HEAP
mode has several advantages:- It allows multiple executors to share the same pool of memory in Tachyon.
- It significantly reduces garbage collection costs.
- Cached data is not lost if individual executors crash.
RDD持久性
Spark中最重要的功能之一是跨操作在内存中持久化(或缓存)数据集。当您持久保存RDD时,每个节点都会存储它在内存中计算的任何分区,并在该数据集(或从中派生的数据集)的其他操作中重用它们。这使得未来的行动更快(通常超过10倍)。缓存是迭代算法和快速交互使用的关键工具。
您可以使用persist()
或cache()
方法标记要保留的RDD 。第一次在动作中计算它时,它将保留在节点的内存中。Spark的缓存是容错的 - 如果RDD的任何分区丢失,它将使用最初创建它的转换自动重新计算。
此外,每个持久化RDD可以使用不同的存储级别进行存储,例如,允许您将数据集保留在磁盘上,将其保留在内存中,但作为序列化Java对象(以节省空间),跨节点复制或存储它在Tachyon堆满了。通过传递StorageLevel
对象(Scala, Java, Python)来设置这些级别 persist()
。该cache()
方法是使用默认存储级别的简写,即StorageLevel.MEMORY_ONLY
(在内存中存储反序列化的对象)。完整的存储级别是:
存储级别 | 含义 |
---|---|
MEMORY_ONLY | 将RDD存储为JVM中的反序列化Java对象。如果RDD不适合内存,则某些分区将不会被缓存,并且每次需要时都会重新计算。这是默认级别。 |
MEMORY_AND_DISK | 将RDD存储为JVM中的反序列化Java对象。如果RDD不适合内存,请存储不适合磁盘的分区,并在需要时从那里读取它们。 |
MEMORY_ONLY_SER | 将RDD存储为序列化 Java对象(每个分区一个字节数组)。这通常比反序列化对象更节省空间,特别是在使用快速序列化器时,但读取CPU密集程度更高。 |
MEMORY_AND_DISK_SER | 与MEMORY_ONLY_SER类似,但将不适合内存的分区溢出到磁盘,而不是每次需要时即时重新计算它们。 |
DISK_ONLY | 仅将RDD分区存储在磁盘上。 |
MEMORY_ONLY_2,MEMORY_AND_DISK_2等 | 与上面的级别相同,但复制两个群集节点上的每个分区。 |
OFF_HEAP(实验性) | 在Tachyon中以序列化格式存储RDD 。与MEMORY_ONLY_SER相比,OFF_HEAP减少了垃圾收集开销,并允许执行器更小并共享内存池,使其在具有大堆或多个并发应用程序的环境中具有吸引力。此外,由于RDD驻留在Tachyon中,执行程序的崩溃不会导致丢失内存缓存。在这种模式下,Tachyon中的内存是可丢弃的。因此,Tachyon不会尝试重建一个从记忆中驱逐的块。如果您打算使用Tachyon作为off堆存储,Spark可以与开箱即用的Tachyon兼容。 有关建议的版本配对,请参阅此页面。 |
注意: 在Python中,存储对象将始终使用Pickle库进行序列化,因此选择序列化级别无关紧要。
reduceByKey
即使没有用户调用,Spark也会在shuffle操作(例如)中自动保留一些中间数据persist
。这样做是为了避免在shuffle期间节点出现故障时重新计算整个输入。我们仍然建议用户persist
在计划重用RDD时调用生成的RDD。
选择哪种存储级别?
Spark的存储级别旨在提供内存使用和CPU效率之间的不同折衷。我们建议您通过以下流程选择一个:
如果您的RDD与默认存储级别(
MEMORY_ONLY
)保持一致,请保持这种状态。这是CPU效率最高的选项,允许RDD上的操作尽可能快地运行。如果没有,请尝试使用
MEMORY_ONLY_SER
并选择快速序列化库,以使对象更加节省空间,但仍然可以快速访问。除非计算数据集的函数很昂贵,否则它们不会溢出到磁盘,或者它们会过滤大量数据。否则,重新计算分区可能与从磁盘读取分区一样快。
如果要快速故障恢复,请使用复制的存储级别(例如,如果使用Spark来处理来自Web应用程序的请求)。所有存储级别通过重新计算丢失的数据提供完全容错,但复制的存储级别允许您继续在RDD上运行任务,而无需等待重新计算丢失的分区。
在具有大量内存或多个应用程序的环境中,实验
OFF_HEAP
模式有几个优点:- 它允许多个执行程序在Tachyon中共享相同的内存池。
- 它显着降低了垃圾收集成本。
- 如果个别执行程序崩溃,缓存数据不会丢失。
package cn.rzlee.spark; import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext; /**
* @Author ^_^
* @Create 2018/11/3
*/
public class Persist { public static void main(String[] args) { SparkConf conf = new SparkConf().setAppName("Persist").setMaster("local[2]");
JavaSparkContext sc = new JavaSparkContext(conf); JavaRDD<String> lines = sc.textFile("C:\\Users\\txdyl\\Desktop\\log\\in\\data.txt", 1).cache();
long beginTime = System.currentTimeMillis();
long count = lines.count();
System.out.println(count);
long endTime = System.currentTimeMillis();
System.out.println("cost "+(endTime - beginTime) + "millisecond"); beginTime = System.currentTimeMillis();
count = lines.count();
System.out.println(count);
endTime = System.currentTimeMillis();
System.out.println("cost "+(endTime - beginTime) + "millisecond"); sc.close();
}
}
什么时候进行 cache?
1.要求的计算速度快
2.集群的资源要足够大
3.重要: cache的数据会多次的触发 Action
4.先进行过滤,然后将缩小范围的数据在 cache到内存
//第一个参数,放到磁盘
//第二个参数,放到内存
//第三个参数,磁盘中的数据,不是以java对象的方式保存
//第四个参数,内存中的数据,以java对象的方式保存
val MEMORY_AND_DISK = new StorageLevel(true true, false, true)
0FF_HEAP:堆外内存( Tachyon,分布式内存存储系统)
Alluxio-Open Source Memory Speed Virtual Distributed Storage
cache使用unpersist(true)释放掉缓存在内存中的数据。
什么时候做 checkpoint?
1.迭代计算,要求保证数据安全
2.对速度要求不高(跟 cache到内存进行对比)
3.将中间结果保存到hdfs
步骤:
//设置 checkpoint目录(分布式文件系统的目录hdfs目录)
//经过复杂进行,得到中间结果
//将中间结果 checkpoint到指定的hdfs目录
//后续的计算,就可以使用前面ck的数据了
Spark- RDD持久化的更多相关文章
- Spark RDD持久化、广播变量和累加器
Spark RDD持久化 RDD持久化工作原理 Spark非常重要的一个功能特性就是可以将RDD持久化在内存中.当对RDD执行持久化操作时,每个节点都会将自己操作的RDD的partition持久化到内 ...
- spark rdd持久化的简单对比
未使用rdd持久化 使用后 通过对比可以发现,未使用RDD持久化时,第一次计算比使用RDD持久化要快,但之后的计算显然要慢的多,差不多10倍的样子 代码 public class PersistRDD ...
- Spark RDD持久化说明
以上说明出自林大贵老师关于Hadoop.spark书籍,如有兴趣请自行搜索购买! 这是我的GitHub分享的一些笔记:https://github.com/mahailuo/pyspark_notes
- Spark RDD概念学习系列之rdd持久化、广播、累加器(十八)
1.rdd持久化 2.广播 3.累加器 1.rdd持久化 通过spark-shell,可以快速的验证我们的想法和操作! 启动hdfs集群 spark@SparkSingleNode:/usr/loca ...
- 【Spark调优】:RDD持久化策略
[场景] Spark对RDD执行一系列算子操作时,都会重新从头到尾计算一遍.如果中间结果RDD后续需要被被调用多次,可以显式调用 cache()和 persist(),以告知 Spark,临时保存之前 ...
- Spark练习之创建RDD(集合、本地文件),RDD持久化及RDD持久化策略
Spark练习之创建RDD(集合.本地文件) 一.创建RDD 二.并行化集合创建RDD 2.1 Java并行创建RDD--计算1-10的累加和 2.2 Scala并行创建RDD--计算1-10的累加和 ...
- Spark的持久化简记
摘要: 1.spark 提供的持久化方法 2.Spark的持久化级别 3.如何选择一种最合适的持久化策略 内容: 1.spark 提供的持久化方法 如果要对一个RDD进行持久化,只要对这个RDD调用c ...
- Spark RDD
对RDD的学习进行一下整理 RDD:基于内存的集群计算容错抽象 分布式内存抽象的概念---弹性分布式数据集(RDD),它具备MapReduce等数据流模型的容错特性,并且允许开发人员在大型集群上执行基 ...
- spark RDD编程,scala版本
1.RDD介绍: RDD,弹性分布式数据集,即分布式的元素集合.在spark中,对所有数据的操作不外乎是创建RDD.转化已有的RDD以及调用RDD操作进行求值.在这一切的背后,Spark会自动 ...
- Spark RDD编程核心
一句话说,在Spark中对数据的操作其实就是对RDD的操作,而对RDD的操作不外乎创建.转换.调用求值. 什么是RDD RDD(Resilient Distributed Dataset),弹性分布式 ...
随机推荐
- asp.net repeater Container.ItemIndex
<asp:Repeater ID="myRepeater" runat="server"> <HeaderTemplate> <t ...
- Flask--上下文源码流程
- oracle中直方图的使用
本文从不绑定变量和绑定变量两种情况讨论直方图的作用 一.不绑定变量 SQL> create table test(name varchar2(10));表已创建.SQL> insert i ...
- 查看系统启动内核检測硬件信息dmesg
dmesg用来显示开机信息.kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dmesg来查看.开机信息亦保存在/var/log文件夹中.名称为dmesg的文件 ...
- 【Mac + Mysql + Navicat Premium】之Navicat Premium如何连接Mysql数据库
参考文章: <mac用brew安装mysql,设置初始密码> 因为我需要连接数据库工具,需要密码,所以下面介绍如何设置.修改密码实现Navicat Premium连接Mysql数据库 建议 ...
- Spring读书笔记-----Spring核心机制:依赖注入
spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.今天就和大家一起来学习一下 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(I ...
- JQ多种刷新方式
下面介绍全页面刷新方法:有时候可能会用到 window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.loc ...
- vue实践---vue不依赖外部资源实现简单多语
vue使用多语,最常见的就是 vue-i18n, 但是如果开发中的多语很少,比如就不到10个多语,这样就没必要引入vue-i18n了, 引入了反正导致代码体积大了,这时候单纯用vue实现多语就是比较好 ...
- textarea中的内容的获取
今天他们说为啥获取不到textarea的数值 这个问题让我很纳闷 为什么会获取不到呢? 按照逻辑来说 同样都是表单元素 怎么可能出现呢? 我就看了一眼代码 alert($("#texta ...
- vuforia 中摄像机的开启与关闭
本文主要讲解的是Unity对Vuforia的开发中在原生调用摄像头上遇到的坑~Unity中调用设备摄像头打开或则关闭,或则开关扫描识别问题等等一些情况~ 下面先说说趟过的坑,再说说解决办法,或则目前没 ...