Spark持久化策略_缓存优化

目录

Spark持久化策略_缓存优化

RDD的持久化策略

cache和persist的源码

MEMORY_ONLY和MEMORY_AND_DISK

总结


Spark持久化策略_缓存优化

RDD的持久化策略

当某个RDD需要进行频繁复用的时候,spark提供RDD的持久化功能,可以通过使用persist()、cache()两种方法进行RDD的持久化。如下所示:

//scala

myRDD.persist()
myRDD.cache()

为什么要使用持久化?

因为RDD1经过Action生成新的RDD2之后,原先的RDD1就会被从内存中删除,如果在接下来的操作中还需要复用到RDD1,Spark会一路向上追溯,重新读取数据,然后重新计算出RDD1,然后进行计算。这会增加磁盘IO和计算成本,持久化会保存数据,等下一次Action时直接使用。

cache和persist的源码

  def persist(newLevel: StorageLevel): this.type = {
    if (isLocallyCheckpointed) {
      // This means the user previously called localCheckpoint(), which should have already
      // marked this RDD for persisting. Here we should override the old storage level with
      // one that is explicitly requested by the user (after adapting it to use disk).
      persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOverride = true)
    } else {
      persist(newLevel, allowOverride = false)
    }
  }

  /**
   * Persist this RDD with the default storage level (`MEMORY_ONLY`).
   */
  def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)

  /**
   * Persist this RDD with the default storage level (`MEMORY_ONLY`).
   */
  def cache(): this.type = persist()

从源码中我们可以看到, cache方法实际上是调用无参数传递的persis方法,所以我们只要研究persist方法即可。而无参的persist默认的参数是StorageLevel.MEMORY_ONLY,我们可以看一下类StorageLevel的源码。

/**
 * Various [[org.apache.spark.storage.StorageLevel]] defined and utility functions for creating
 * new storage levels.
 */
object StorageLevel {
  val NONE = new StorageLevel(false, false, false, false)
  val DISK_ONLY = new StorageLevel(true, false, false, false)
  val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
  val MEMORY_ONLY = new StorageLevel(false, true, false, true)
  val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
  val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
  val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
  val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
  val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
  val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
  val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
  val OFF_HEAP = new StorageLevel(true, true, true, false, 1)

  /**
   * :: DeveloperApi ::
   * Return the StorageLevel object with the specified name.
   */
  @DeveloperApi
  def fromString(s: String): StorageLevel = s match {
    case "NONE" => NONE
    case "DISK_ONLY" => DISK_ONLY
    case "DISK_ONLY_2" => DISK_ONLY_2
    case "MEMORY_ONLY" => MEMORY_ONLY
    case "MEMORY_ONLY_2" => MEMORY_ONLY_2
    case "MEMORY_ONLY_SER" => MEMORY_ONLY_SER
    case "MEMORY_ONLY_SER_2" => MEMORY_ONLY_SER_2
    case "MEMORY_AND_DISK" => MEMORY_AND_DISK
    case "MEMORY_AND_DISK_2" => MEMORY_AND_DISK_2
    case "MEMORY_AND_DISK_SER" => MEMORY_AND_DISK_SER
    case "MEMORY_AND_DISK_SER_2" => MEMORY_AND_DISK_SER_2
    case "OFF_HEAP" => OFF_HEAP
    case _ => throw new IllegalArgumentException(s"Invalid StorageLevel: $s")
  }
  /**
   * :: DeveloperApi ::
   * Create a new StorageLevel object.
   */
  @DeveloperApi
  def apply(
      useDisk: Boolean,
      useMemory: Boolean,
      useOffHeap: Boolean,
      deserialized: Boolean,
      replication: Int): StorageLevel = {
    getCachedStorageLevel(
      new StorageLevel(useDisk, useMemory, useOffHeap, deserialized, replication))
  }

  /**
   * :: DeveloperApi ::
   * Create a new StorageLevel object without setting useOffHeap.
   */
  @DeveloperApi
  def apply(
      useDisk: Boolean,
      useMemory: Boolean,
      deserialized: Boolean,
      replication: Int = 1): StorageLevel = {
    getCachedStorageLevel(new StorageLevel(useDisk, useMemory, false, deserialized, replication))
  }

可以看到,StorageLevel参数包括:

参数:默认含义
useDisk: Boolean是否使用磁盘做持久化
useMemory: Boolean是否使用内存做持久化
useOffHeap: Boolean是否使用JAVA堆内存
deserialized: Boolean是否序列化
replication:1副本数(做容错)

所以我们可以得到:

  • NONE:是默认的配置
  • DISK_ONLY:仅仅缓存于磁盘
  • DISK_ONLY_2:仅仅缓存于磁盘并且保持2个副本
  • MEMORY_ONLY:仅仅缓存于磁盘内存
  • MEMORY_ONLY_2:仅仅缓存于磁盘内存并且保持2个副本
  • MEMORY_ONLY_SER:仅仅缓存于磁盘内存且序列化
  • MEMORY_ONLY_SER_2:仅仅缓存于磁盘内存且序列化和保持2个副本
  • MEMORY_AND_DISK:缓存于内存满之后,就会缓存于磁盘
  • MEMORY_AND_DISK_2:缓存于内存满之后,就会缓存于磁盘并且保持2个副本
  • MEMORY_AND_DISK_SER:缓存于内存满之后,就会缓存于磁盘且序列化
  • MEMORY_AND_DISK_SER_2:缓存于内存满之后,就会缓存于磁盘且序列化,以及保持2个副本
  • OFF_HEAP:缓存远离堆内存

序列化可以类似于压缩,便于节省存储空间,但会增加计算成本,因为每次使用需要序列化以及反序列化;副本数量默认为1,是为了防止数据丢失,增强容错能力;OFF_HEAP将RDD存储在etachyon上,使得具有更低的垃圾回收开销,了解即可;DISK_ONLY没什么可说的,下面主要比较MEMORY_ONLY和MEMORY_AND_DISK。

MEMORY_ONLY和MEMORY_AND_DISK

MEMORY_ONLY:RDD仅缓存与内存中,内存中放不下的分区将在被使用时重新从磁盘读取数据并计算。

MEMORY_AND_DISK:尽量往内存中存,存不下的分区将会被保存在磁盘中,避免了重算的过程。

直观看来,MEMORY_ONLY还需要计算过程,效率相对来说较低,但事实上,由于是在内存中进行计算,所以重新计算时间消耗是远小于磁盘IO的,所以通常默认使用MEMORY_ONLY。除非中间计算开销特别大,这时候使用MEMORY_AND_DISK才会是一个更好的选择。

总结

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值