六、持久化
如果简单的对
RDD
调用行动操作,则Spark
每次都会重新计算RDD
以及它所有的依赖RDD
。- 在迭代算法中,消耗会格外大。因为迭代算法通常会使用同一组数据。
当我们让
spark
持久化存储一个RDD
时,计算出RDD
的节点会分别保存它们所求出的分区数据。- 如果一个拥有持久化数据的节点发生故障,则
spark
会在需要用到该缓存数据时,重新计算丢失的分区数据。 - 我们也可以将数据备份到多个节点上,从而增加对数据丢失的鲁棒性。
- 如果一个拥有持久化数据的节点发生故障,则
我们可以为
RDD
选择不同的持久化级别:在pyspark.StorageLevel
中:MEMORY_ONLY
:数据缓存在内存中。- 内存占用:高;
CPU
时间:低;是否在内存:是;是否在磁盘中:否。
- 内存占用:高;
MEMORY_ONLY_SER
:数据经过序列化之后缓存在内存中。- 内存占用:低;
CPU
时间:高;是否在内存:是;是否在磁盘中:否。
- 内存占用:低;
MEMORY_AND_DISK
:数据缓存在内存和硬盘中。- 内存占用:高;
CPU
时间:中等;是否在内存:部分;是否在磁盘中:部分。 - 如果数据在内存中放不下,则溢写到磁盘上。如果数据在内存中放得下,则缓存到内存中
- 内存占用:高;
MEMORY_AND_DISK_SER
:数据经过序列化之后缓存在内存和硬盘中。- 内存占用:低;
CPU
时间:高;是否在内存:部分;是否在磁盘中:部分。 - 如果数据在内存中放不下,则溢写到磁盘上。如果数据在内存中放得下,则缓存到内存中
- 内存占用:低;
DISK_ONLY
:数据缓存在磁盘中 。- 内存占用:低;
CPU
时间:高;是否在内存:否;是否在磁盘中:是。
- 内存占用:低;
如果在存储级别末尾加上数字
N
,则表示将持久化数据存储为N
份。如:MEMORY_ONLY_2 #表示对持久化数据存储为 2 份
在
python
中,总是使用pickle library
来序列化对象,因此在python
中可用的存储级别有:MEMORY_ONLY、MEMORY_ONLY_2、MEMORY_AND_DISK、MEMORY_AND_DISK_2、DISK_ONLY、DISK_ONLY_2
.persist(storageLevel=StorageLevel(False, True, False, False, 1))
:对当前RDD
进行持久化- 该方法调用时,并不会立即执行持久化,它并不会触发求值,而仅仅是对当前
RDD
做个持久化标记。一旦该RDD
第一次求值时,才会发生持久化。 .persist()
的默认行为是:将数据以序列化的形式缓存在JVM
的堆空间中
- 该方法调用时,并不会立即执行持久化,它并不会触发求值,而仅仅是对当前
.cache()
:它也是一种持久化调用。- 它等价于
.persist(MEMORY_ONLY)
- 它不可设定缓存级别
- 它等价于
.unpersist()
:标记当前RDD
是未缓存的,并且将所有该RDD
已经缓存的数据从内存、硬盘中清除。当要缓存的数据太多,内存放不下时,
spark
会利用最近最少使用(LRU
) 的缓存策略,把最老的分区从内存中移除。- 对于
MEMORY_ONLY、MEMORY_ONLY_SER
级别:下一次要用到已经被移除的分区时,这些分区就要重新计算 - 对于
MEMORY_AND_DISK、MEMORY_AND_DISK_SER
级别:被移除的分区都会被写入磁盘。
- 对于
.getStorageLevel()
:返回当前的缓存级别