(四)Spark源码理解之BlockManager---part3

本文深入探讨了Spark生态系统中BlockManagerMaster与BlockManager的角色与功能,包括它们如何管理和存储块数据,以及两者之间的交互机制。重点介绍了BlockManagerMasterActor的重要方法,以及BlockManager如何实现从内存或磁盘中删除RDD信息的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.4 BlockStatus

存储了Block块的存储级别(是内存存储还是磁盘存储等),内存,磁盘以及tachyon的大小

BlockManagerMasterActor有很多比较重要的方法,正是由于这些方法才使得主节点可以管理块(分区)

private def removeRdd(rddId: Int): Future[Seq[Int]] = {//返回的是一个Seq[Int],是因为RDD存在依赖关系,返回的就是rdd以及其所依赖的父rdd
    val blocks = blockLocations.keys.flatMap(_.asRDDId).filter(_.rddId == rddId)//因为是删除rdd,所以首先将BlockId转换为RDDBlockId,再过滤出要求的rdd
    blocks.foreach { blockId =>
      val bms: mutable.HashSet[BlockManagerId] = blockLocations.get(blockId)
      bms.foreach(bm => blockManagerInfo.get(bm).foreach(_.removeBlock(blockId)))// 在BlockManagerInfo中删除指定的block
      blockLocations.remove(blockId)//在blockLocations中删除rdd的记录
    }
         import context.dispatcher
    val removeMsg = RemoveRdd(rddId)
    Future.sequence(
      blockManagerInfo.values.map { bm =>
        bm.slaveActor.ask(removeMsg)(akkaTimeout).mapTo[Int]
      }.toSeq
    )//传递删除rdd的消息
  }

















BlockManager也有removeRdd()方法,不同的是BlockManager是从内存或者磁盘中删除该RDD所拥有的数据库信息,还有其他的一些方法,如获取块状态(它用到的就是BlockManagerInfo类中的getBlockStatus方法),获取存储状态,注册一个块管理器信息BlockManagerInfo等等,因为这些方法都比较容易理解,因此就不加以赘述.

个人觉得BlockManagerMaster,BlockManagerMasterActor等之间的关系大概可以表示为:


3.BlockManager

BlockManager为块管理器,它将BlockManagerMaster包裹了,初始化时会注册一个BlockManagerMaster,依靠BlockManagerMaster来管理块(这就和后面TaskScheduler依靠TaskSchedulerImpl来进行实际的任务调度有点类似),获得块管理器或者块信息和数据,BlockManager还定义了ShuffleBlockManager(专门负责shuffle的文件读写,这在生成ShuffleMapTask时会用到,比较复杂)和DiskBlockManager(将块的逻辑地址(以Id标识)转换为磁盘上的物理块,这里就进行实际的存储操作了),其中有个比较重要的方法,如下面代码所示:

def getFile(filename: String): File = {
      val hash = Utils.nonNegativeHash(filename)//计算相应文件的哈希值
    val dirId = hash % localDirs.length//本地目录,通过createLocalDirs创建
    val subDirId = (hash / localDirs.length) % subDirsPerLocalDir
        var subDir = subDirs(dirId)(subDirId)// subDirs是一个文件的二维矩阵
    if (subDir == null) {
      subDir = subDirs(dirId).synchronized {
        val old = subDirs(dirId)(subDirId)//检测该文件是否存在,其中dirId等就是块的逻辑地址
        if (old != null) {
          old
        } else {
          val newDir = new File(localDirs(dirId), "%02x".format(subDirId))
          newDir.mkdir()//如果不存在,则创建新的文件
          subDirs(dirId)(subDirId) = newDir
          newDir
        }
      }
    }


看到上面的代码忽然想到类BlockId中每种类型的BlockId都有个name方法,如RDDBlockId



可能就是这个name方法的返回值传给getFile,获得哈希值,进而创建目录

未完待续。。。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值