Spark原始碼分析之DiskBlockMangaer分析

happy19870612發表於2017-11-10

建立和維護邏輯上的block和磁碟上的物理位置之間的對映,預設情況下,一個block對映一個檔案,檔名字一般是blockId。但是,也有可能有多個資料塊對映到一個檔案的一個段,block檔案在配置的spark.local.dir目錄下的目錄之間根據hash演算法存放。我們可以配置

spark.diskStore.subDirectories配置子檔案目錄數

一 核心屬性

BlockManager blockManager: 主要進行block增刪改

Int subDirsPerLocalDir: 子目錄數量預設64個

Array[File] localDirs: 本地用於存放block檔案的一級目錄

Array[File] subDirs: 子檔案

二 重要方法

2.1getFile 獲取一個檔案

defgetFile(filename:String): File = {
  // 根據檔名進行hash
 
val hash= Utils.nonNegativeHash(filename)
  // 根據檔名的hashcode,首先看這個檔案位於哪一個一級目錄
 
val dirId= hash % localDirs.length
 
// 再決定子目錄位於哪一個一級目錄中
 
val subDirId= (hash / localDirs.length) %subDirsPerLocalDir

 
// 如果子目錄不存在則建立
 
val subDir= subDirs(dirId).synchronized {
    val old = subDirs(dirId)(subDirId)
    if (old != null) {
      old
   
} else {
      val newDir = new File(localDirs(dirId),"%02x".format(subDirId))
      if (!newDir.exists() && !newDir.mkdir()) {
        throw new IOException(s"Failed to create localdir in$newDir.")
      }
      subDirs(dirId)(subDirId) =newDir
      newDir
   
}
  }
  // 根據目錄和檔名建立檔案
 
new File(subDir,filename)
}

 

// 使用blockId作為檔名建立檔案
def getFile(blockId: BlockId): File = getFile(blockId.name)

 

 

2.2containsBlock 檢查磁碟上是否存在blockId這樣的block

實就是看是否磁碟上是否存在檔名為blockId的檔案一個檔案就對應著一個block

defcontainsBlock(blockId: BlockId): Boolean = {
  getFile(blockId.name).exists()
}

 

2.3getAllFiles 查詢當前磁碟上所有的 檔案

def getAllFiles(): Seq[File] = {
  // Get all the files inside the array of array of directories
  subDirs.flatMap { dir =>
    dir.synchronized {
      // Copy the content of dir because it may be modified in other threads
      dir.clone()
    }
  }.filter(_ != null).flatMap { dir =>
    val files = dir.listFiles()
    if (files != null) files else Seq.empty
  }
}

 

 

2.4getAllBlocks 查詢出儲存在磁碟上所有的block,其實就是查詢磁碟上所有的block對應的檔案而已

def getAllBlocks(): Seq[BlockId] = {
  getAllFiles().map(f => BlockId(f.getName))
}

 

2.5 createTempLocalBlock 建立臨時的本地block

def createTempLocalBlock(): (TempLocalBlockId, File) = {
  var blockId = new TempLocalBlockId(UUID.randomUUID())
  while (getFile(blockId).exists()) {
    blockId = new TempLocalBlockId(UUID.randomUUID())
  }
  (blockId, getFile(blockId))
}

 

2.5createTempShuffleBlock 建立臨時的本地shuffle block

def createTempShuffleBlock(): (TempShuffleBlockId, File) = {
  var blockId = new TempShuffleBlockId(UUID.randomUUID())
  while (getFile(blockId).exists()) {
    blockId = new TempShuffleBlockId(UUID.randomUUID())
  }
  (blockId, getFile(blockId))
}

 

相關文章