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

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等之间的关系大概可以表示为:

(四)Spark源码理解之BlockManager---part3_第1张图片

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,获得哈希值,进而创建目录

未完待续。。。





你可能感兴趣的:(Spark学习)