【Spark】Spark 存储原理--写数据过程

本篇结构:

  • 写数据块过程
  • 写内存
  • 写磁盘
  • 写远程

一、写数据块过程

分析读数据过程时,可以了解到 RDD.iterator -> RDD.getOrCompute -> BlockManager.getOrElseUpdate 既是读数据的入口,也是写数据的入口。

不同的是,读数据走 BlockManager.get 方法,而写数据走 doPutIterator 方法。

在 doPutIterator 方法中,如果缓存到内存中,则需要先判断数据是否进行了反序列化,如果已经反序列化,调用 putIteratorAsValues 直接把数据存入内存,读取时不需要再进行反序列化,如果没有反序列化,则调用 putIteratorAsBytes 方法将序列化数据缓存,读取时需要进行反序列化。在存入内存时,需要判断在内存中展开该数据大小是否足够,如果足够,MemoryStore 直接 存入 entries 中,如果不够,如果启用磁盘存储,则存入磁盘。

数据写入完成时,一方面把数据块的元数据发送给 Driver 端的 BlockManagerMasterEndpoint 终端点,更新元数据。另一方面判断是否需要创建数据副本,如果需要则调用 replicate 方法,把数据写到远程节点。

过程图如下:

BlockManager # doPutIterator:

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) { channel =>
                val out = Channels.newOutputStream(channel)
                serializerManager.dataSerializeStream(blockId, out, 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 $blockI
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值