[Spark]-RDD的持久化
5.RDD的持久化
5.1 概述
Spark一个很重要的能力就是支持对RDD的持久化(或者说缓存),并且在多个操作可以访问这些持久化数据,从从而无需再重新计算.
对于RDD的持久化,Spark还有个很重要的能力就是容错的: 如果RDD的某个分区丢失了,它会自动的根据它的源RDD重新计算
5.2 存储级别
persist(),可以自由选择持久化的存储级别,将RDD持久化硬盘,内存(必须是Java可序列化类型),副本到多个节点.
cache(),相当于persist的快捷方式,使用默认存储级别(StorageLevel.MEMORY_ONLY
)持久化数据.
具体的持久化级别如下:
日志级别 | 描述 |
MEMORY_ONLY | 默认级别.将RDD作为一个可序列化的Java对象保存到JVM的内存中(如果内存空间不够,部分分区将不会持久化,只能在需要时再重新计算) |
MEMORY_AND_DISK | 将RDD作为一个可序列化的Java对象保存到JVM的内存中(如果内存空间不够,部分分区将持久化到磁盘,需要时直接读取) |
MEMORY_ONLY_SER (Java and Scala) | 将RDD序列化为一个Java对象(每个分区一个byte数组),这样可以更加节省空间(特别是fast serializer),但读取时会增加更多的CPU负担 |
MEMORY_AND_DISK_SER(Java and Scala) | 同MEMORY_ONLY_SER,但内存空间不足时,会溢写到磁盘 |
DISK_ONLY | 全部存储到磁盘 |
MEMORY_ONLY_2,MEMORY_AND_DISK_2,等等 | 存储与前面相同,但每个存储会存储为两份数据(副本) |
OFF_HEAP (实验版本) |
注意.在Python中,会始终使用Pickle进行序列化,不关心你选择使用哪种序列化方式
在Python中,存储级别也只支持 MEMORY_ONLY
, MEMORY_ONLY_2
, MEMORY_AND_DISK
, MEMORY_AND_DISK_2
, DISK_ONLY
, and DISK_ONLY_2
另外,在shuffle操作中,Spark会自动的对中间结果进行缓存(哪怕你没有使用persist),但仍然建议如果你需要反复使用某个RDD时,手动的缓存它.
5.3 存储级别的选择
选择哪种存储级别,实际是在内存耗用和CPU耗用之间做一个效率的权衡.Spark有如下的建议:
如果MEMORY_ONLY是有效的(没有内存不够导致的溢出),那就选择MEMORY_ONLY.这是对CPU耗用最小的做法,也是运行计算最快的做法
否则就尝试使用MEMORY_ONLY_SER并挑选一个快速序列化库.这将会占用更小的内存控件,并且依然计算非常迅速的
除非重计算RDD代价非常高,或者是需要过滤大量的数据的情况下,才会考虑溢写到磁盘.因为重新计算这个RDD的耗用可能会与从磁盘上读取这个RDD耗用差不多
如果想要快速恢复出现异常的RDD,建议使用副本机制
5.4 删除持久化
Spark会自动的监控各持久化的对象的使用情况,并依据最近最少使用原则( least-recently-used (LRU))将持久化数据删除.
也可以RDD.unpersist()手动删除一个RDD的持久化数据.