spark的持久化机制做的相对隐晦一些,没有一个显示的调用入口。

首先通过rdd.persist(newLevel: StorageLevel)对此rdd的StorageLevel进行赋值,同checkpoint一样,本身没有进行之久化操作。真正进行持久化操作实在之后的第一个action 中通过iterator方法进行调用:

  final def iterator(split: Partition, context: TaskContext): Iterator[T] = {
if (storageLevel != StorageLevel.NONE) {
getOrCompute(split, context)
} else {
computeOrReadCheckpoint(split, context)
}
}
其中调用过持久化的rdd的StorageLevel不为NONE,所以会执行getOrCompute方法
if (storageLevel != StorageLevel.NONE) {
getOrCompute(split, context)
}
  /**
* Gets or computes an RDD partition. Used by RDD.iterator() when an RDD is cached.
*/
private[spark] def getOrCompute(partition: Partition, context: TaskContext): Iterator[T] = {
//TODO block和partition的关系
val blockId = RDDBlockId(id, partition.index)
var readCachedBlock = true
// This method is called on executors, so we need call SparkEnv.get instead of sc.env.
SparkEnv.get.blockManager.getOrElseUpdate(blockId, storageLevel, elementClassTag, () => {
readCachedBlock = false
computeOrReadCheckpoint(partition, context)
}) match {
case Left(blockResult) =>
if (readCachedBlock) {
val existingMetrics = context.taskMetrics().inputMetrics
existingMetrics.incBytesRead(blockResult.bytes)
new InterruptibleIterator[T](context, blockResult.data.asInstanceOf[Iterator[T]]) {
override def next(): T = {
existingMetrics.incRecordsRead(1)
delegate.next()
}
}
} else {
new InterruptibleIterator(context, blockResult.data.asInstanceOf[Iterator[T]])
}
case Right(iter) =>
new InterruptibleIterator(context, iter.asInstanceOf[Iterator[T]])
}
}
getOrCompute方法中,调用了blockManager.getOrElseUpdate方法实现了block的读取和持久化操作:
SparkEnv.get.blockManager.getOrElseUpdate(blockId, storageLevel, elementClassTag, () => {
readCachedBlock = false
computeOrReadCheckpoint(partition, context)
})

在getOrElseUpdate中调用doPutIterator方法,具体实现存储方式和级别的逻辑判断进而调用相应的存储实现MemoryStore或者DiskStore进行具体实现。

private def  doPutIterator[T](
blockId: BlockId,
iterator: () => Iterator[T],
level: StorageLevel,
classTag: ClassTag[T],
tellMaster: Boolean = true,
keepReadLock: Boolean = false): Option[PartiallyUnrolledIterator[T]] = {
doPut(blockId, level, classTag, tellMaster = tellMaster, keepReadLock = keepReadLock) { info =>
val startTimeMs = System.currentTimeMillis
var iteratorFromFailedMemoryStorePut: Option[PartiallyUnrolledIterator[T]] = None
// Size of the block in bytes
var size = 0L
if (level.useMemory) {
// Put it in memory first, even if it also has useDisk set to true;
// We will drop it to disk later if the memory store can't hold it.
if (level.deserialized) {
memoryStore.putIteratorAsValues(blockId, iterator(), classTag) match {
case Right(s) =>
size = s
case Left(iter) =>
// Not enough space to unroll this block; drop to disk if applicable
if (level.useDisk) {
logWarning(s"Persisting block $blockId to disk instead.")
diskStore.put(blockId) { fileOutputStream =>
serializerManager.dataSerializeStream(blockId, fileOutputStream, iter)(classTag)
}
size = diskStore.getSize(blockId)
} else {
iteratorFromFailedMemoryStorePut = Some(iter)
}
}
} else { // !level.deserialized
memoryStore.putIteratorAsBytes(blockId, iterator(), classTag, level.memoryMode) match {
case Right(s) =>
size = s
case Left(partiallySerializedValues) =>
// Not enough space to unroll this block; drop to disk if applicable
if (level.useDisk) {
logWarning(s"Persisting block $blockId to disk instead.")
diskStore.put(blockId) { fileOutputStream =>
partiallySerializedValues.finishWritingToStream(fileOutputStream)
}
size = diskStore.getSize(blockId)
} else {
iteratorFromFailedMemoryStorePut = Some(partiallySerializedValues.valuesIterator)
}
}
} } else if (level.useDisk) {
diskStore.put(blockId) { fileOutputStream =>
serializerManager.dataSerializeStream(blockId, fileOutputStream, iterator())(classTag)
}
size = diskStore.getSize(blockId)
} val putBlockStatus = getCurrentBlockStatus(blockId, info)
val blockWasSuccessfullyStored = putBlockStatus.storageLevel.isValid
if (blockWasSuccessfullyStored) {
// Now that the block is in either the memory or disk store, tell the master about it.
info.size = size
if (tellMaster && info.tellMaster) {
reportBlockStatus(blockId, putBlockStatus)
}
addUpdatedBlockStatusToTaskMetrics(blockId, putBlockStatus)
logDebug("Put block %s locally took %s".format(blockId, Utils.getUsedTimeMs(startTimeMs)))
if (level.replication > 1) {
val remoteStartTime = System.currentTimeMillis
val bytesToReplicate = doGetLocalBytes(blockId, info)
// [SPARK-16550] Erase the typed classTag when using default serialization, since
// NettyBlockRpcServer crashes when deserializing repl-defined classes.
// TODO(ekl) remove this once the classloader issue on the remote end is fixed.
val remoteClassTag = if (!serializerManager.canUseKryo(classTag)) {
scala.reflect.classTag[Any]
} else {
classTag
}
try {
replicate(blockId, bytesToReplicate, level, remoteClassTag)
} finally {
bytesToReplicate.unmap()
}
logDebug("Put block %s remotely took %s"
.format(blockId, Utils.getUsedTimeMs(remoteStartTime)))
}
}
assert(blockWasSuccessfullyStored == iteratorFromFailedMemoryStorePut.isEmpty)
iteratorFromFailedMemoryStorePut
}
}

spark 持久化机制的更多相关文章

  1. 60、Spark Streaming:缓存与持久化机制、Checkpoint机制

    一.缓存与持久化机制 与RDD类似,Spark Streaming也可以让开发人员手动控制,将数据流中的数据持久化到内存中.对DStream调用persist()方法,就可以让Spark Stream ...

  2. Spark 概念学习系列之Spark存储管理机制

    Spark存储管理机制 概要 01 存储管理概述 02 RDD持久化 03 Shuffle数据存储 04 广播变量与累加器 01 存储管理概述 思考: RDD,我们可以直接使用而无须关心它的实现细节, ...

  3. Redis提供的持久化机制(RDB和AOF)

    Redis提供的持久化机制 Redis是一种面向"key-value"类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却 ...

  4. ActiveMQ的几种消息持久化机制

    为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制. ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB,无论使用哪种持久化方式 ...

  5. Spark工作机制简述

    Spark工作机制 主要模块 调度与任务分配 I/O模块 通信控制模块 容错模块 Shuffle模块 调度层次 应用 作业 Stage Task 调度算法 FIFO FAIR(公平调度) Spark应 ...

  6. Redis 学习之持久化机制、发布订阅、虚拟内存

    一.持久化机制 Redis是一个支持持久化的内存数据库,redis会经常将内存中的数据同步到硬盘上来保证数据持久化,从而避免服务器宕机数据丢失问题,或者减少服务器内存消耗提高性能. 持久化方式: 1. ...

  7. ActiveMQ的消息持久化机制

    为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制. ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB,无论使用哪种持久化方式 ...

  8. Redis学习-持久化机制

    Redis持久化的意义 在于故障恢复 比如你部署了一个redis,作为cache缓存,当然也可以保存一些较为重要的数据 如果没有持久化的话,redis遇到灾难性故障的时候(断电.宕机),就会丢失所有的 ...

  9. 分析RedisRDB和AOF两种持久化机制的工作原理及优劣势

    一.RDB和AOF两种持久化机制的介绍 RDB持久化机制,对redis中的数据执行周期性的持久化 AOF机制对每条写入命令作为日志,以append-only(追加)的模式写入一个日志文件中,在redi ...

随机推荐

  1. webpack 的第三方库分离并持久化缓存

    我们常常需要在浏览器缓存一些稳定的资源,如第三方库等.要达到这个目标,只需要两步: 1.提取出“稳定的资源”: 2.提供稳定的文件hash . 处理后的出的文件就像这样子: app.1w3ad4q4. ...

  2. 51nod加农炮

    这道题维护一下前缀最大值然后二分答案就好了哇 233 #include<cstdio> #include<cstring> #include<algorithm> ...

  3. 关于UML

    http://www.cnblogs.com/zfc2201/archive/2011/08/16/2141433.html

  4. [bzoj3224]Tyvj 1728 普通平衡树——splay模板

    题目 你需要写一种数据结构支援以下操作. 插入元素. 删除元素. 查询元素的排名. 查询第k小的元素. 查询元素前趋. 查询元素后继. 题解 BBST裸题. 代码 #include <cstdi ...

  5. Opencv 学习笔记之——鼠标,进度条操作

    Opencv中提供一个鼠标调用的函数,SetMouseCallback()函数,它配合一个回调函数来实现鼠标操作的功能.   首先看一下SetMouseCallback的函数原型: c++: void ...

  6. 自动化测试===【转】Robot Framework作者建议如何选择自动化测试框架

    原文:http://www.infoq.com/cn/news/2012/06/robot-author-suggest-autotest 软件自动化测试,作为手工测试的替代,越来越受到关注.Pekk ...

  7. 操作MySQL数据库相关代码

    注意事项: 1.导入驱动包,如我导的是mysql-connector-java-5.1.26-bin.jar 2.修改下面代码中的用户名和密码 3.其中URL为"jdbc:mysql://数 ...

  8. 【 Linux 】三大主流软件负载均衡器对比(LVS、Nginx、HAproxy)

    三大主流软件负载均衡器对比(LVS.Nginx.HAproxy) (资料来自网络,做了部分的补充说明) LVS:    1. 抗负载能力强,性能高,能达到F5的60%,对内存和CPU资源消耗比较低   ...

  9. P1029 最大公约数和最小公倍数问题

    题目描述 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1.P,Q是正整数 2.要求P,Q以x0为 ...

  10. hadoop3.1伪分布式部署

    1.环境准备 系统版本:CentOS7.5 主机名:node01 hadoop3.1 的下载地址: http://mirror.bit.edu.cn/apache/hadoop/common/hado ...