走进spark(二) rdd.persist

本文深入探讨了Spark中RDD的persist方法,详细解释了如何通过不同的StorageLevel配置来实现内存或磁盘的数据持久化,以及persist方法的具体实现流程。

走进spark(二) rdd.persisit

上篇我们讲到通过调用rdd.checkpoint,可以将rdd存储在磁盘,除此之外rdd还有一个有意思的持久化方法rdd.persist,代码如下:

defpersist(newLevel: StorageLevel):this.type= {
 
// TODO:Handle changes of StorageLevel
 
if (storageLevel!= StorageLevel.NONE&&newLevel != storageLevel) {//storageLevel一致性检查
   
throw new UnsupportedOperationException(
     
"Cannot change storage level of an RDD after it wasalready assigned a level")
  }
  sc.persistRDD(
this)
 
// Register the RDD with the ContextCleaner for automaticGC-based cleanup
 
sc.cleaner.foreach(_.registerRDDForCleanup(this))//这个有必要研究一番,等再开一篇吧
 
storageLevel = newLevel
 
this
}

在此方法中首先对rdd的storageLevel进行了一致性检查,如果已经初始化了storageLevel,那么你无法通过persist方法改变其storageLevel.这里先看下StorageLevel:

classStorageLevel private(
   
private var useDisk_ :Boolean,
    private var
useMemory_ : Boolean,
    private var
useOffHeap_ :Boolean,
    private var
deserialized_ :Boolean,
    private var
replication_ :Int = 1)

 

objectStorageLevel {
 
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(false,false, true, false)

  …

}

我很好奇DISK_ONLYcheckpoint有什么区别。

在persist方法中,调用了sc.persistRDD(this),这是sparkContext的一个方法:

private[spark] def persistRDD(rdd: RDD[_]) {
  persistentRdds(rdd.id) = rdd // private[spark] val persistentRdds = new TimeStampedWeakValueHashMap[Int, RDD[_]]
}

其实就是将(rdd.id,rdd)放到了一个TimeStampedWeakValueHashMap中,并没有做实质性的存储的动作,也就是说实质性的存储方法在其他的地方,我们得去看rdd参加计算的时候,程序是通过什么方法获取到rdd的,就可以找到这段代码。由于涉及到任务调度系统,这段代码的调用栈十分冗长,以rdd.count为例:

Rdd.count->sparkContex.runjob->dagScheduler.runjob->dagScheduler.submitjob-> dagScheduler.receive-> dagScheduler.handleJobSubmitted->

dagScheduler .submitStage-> dagScheduler.submitMissingTasks--à taskSchedulerImpl.submitTasks->schedulableBuilder.addTaskSetManager->…task.run->rdd. iterator-> CacheManager.getorcompute->blockManager.put-> blockManager.doput,部分代码如下:

 

 

 

      if(level.useMemory) {
       
// Save it just to memory first, even if it also hasuseDisk set to true; we will
        // drop it to disk later if thememory store can't hold it.
       
val res= datamatch {
         
case IteratorValues(iterator)=>
           
memoryStore.putValues(blockId,iterator, level, true)
         
case ArrayBufferValues(array)=>
           
memoryStore.putValues(blockId,array, level, true)
         
case ByteBufferValues(bytes)=>
            bytes.rewind()
           
memoryStore.putBytes(blockId,bytes, level)
        }

以上是level.useMemory,调用的方法栈memoryStore.putValues->memoryStore. tryToPut,如下:

 

实际上的持久化的操作就在tryput之中,需要细读,今天太累了,看了半天有几个点懂,休息下,下次接着来:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值