spark学习-43-Spark的BlockManager

来源:互联网 发布:人力资源软件排名2016 编辑:程序博客网 时间:2024/06/06 06:50

1.简介:
  BlockManager负责对Block的管理,只有在BlockManager的痴实话方法initialize被调用之后,它才是有效的。Blockmanager作为存储系统的一部分。

BlockManager是Spark存储体系中的核心组件。
BlockManager主要由以下部分组成:
  1.shuffle客户端ShuffleClient;
   2.BlockManagerMaster(对存在于所有Executor上的BlockManager统一管理)
  3.磁盘块管理器DiskBlockManager;
  4.内存存储MemoryStore;
  5.磁盘存储DiskStore;
  6.Tachyon存储TachyonStore;
  7.非广播Block清理器metadataCleanner和广播Block清理器broadcastCleaner;
  8.压缩算法实现CompressionCodee;

BlockManager也是Master-slaves结构。Driver中的BlockManager会管理所有Executor中的BlockManager,在Executor启动时,会启动相应的BlockManager。
其次,BlockManager提供了读取和写数据的接口,可以从本地读写数据,也可以从远程读写数据。BlockManager管理的数据可以是存储在内存、磁盘以及OffHeap(堆外空间,例如Tachyon)。

2. BlockManager运行原理图
这里写图片描述

这张图很重要仔细看看
对上图一些概念进行解析:
  (1) driver和executor请看:http://blog.csdn.net/qq_21383435/article/details/78653427

  (2) BlockManagerMaster对整个集群的Block数据进行管理,Block是Spark处理数据的基本单位,其与数据存储在哪里无关。
  作为BlockManagerMasterEndpoint的代理类,隐藏实体类
  执行BlockManager中注册等操作

  (3) MspOutputTakerMaster
    主要用于跟踪所有的Mapper的输出的。

  (4) BlockManagerMasterEndpoint其本身是一个消息循环体,会负责通过远程消息通信的方式去管理所有的节点的BlockManager。
   构造BlockmangerMaster时,其内部有个成员是BlockManagerMasterEndpoint。
    BlockManagerMasterEndpoint是BlcokManagerMaster的一个成员,在BlockManagerMaster实例化时产生,并开始接收其他BlcokManager向它发送注册信息。

 (5)BlockManagerMasterEndpoint
   响应远程调用的实体类
  维护BlockManager的元数据
  拥有移除RDD、获取Block和更新BlockInfo等功能

 (6) MemoryStore是BlockManager中专门负责内存数据存储和读写的类。

 (7) DiskStore 是BlockManager中专门负责基于磁盘的数据存储和读写的类。

 (8) DiskBlockManager管理logical Block与磁盘上的physical Block之间的映射关系并负责磁盘的文件的创建、读写等。

 (9) BlockManagerInfo
   维护着每个BlockManager中所管理的Block
   持有BlockManagerSlaveEndpoint的实例

 (10) BlockManagerId:BlockManagerId源码解析
   作为每个BlockManager的唯一标识

 (11) StorageLevel
   用来描述Block的存储级别(存储位置、是否序列化和副本数)

3.BlockManager是在sparkEnv初始化的时候创建的

// =================================.创建块传输服务BlockTransferService;===========================    /*        blockTransferService默认为NettyBlockTransferService(可以配置属相spark.shuffle.blockTransferService使用NioBlockTransferService)        ,它使用Netty法人一步时间驱动的网络应用框架,提供web服务及客户端,获取远程节点上的Block集合。     */    val blockManagerPort = if (isDriver) {      conf.get(DRIVER_BLOCK_MANAGER_PORT)    } else {      conf.get(BLOCK_MANAGER_PORT)    }    val blockTransferService =      new NettyBlockTransferService(conf, securityManager, bindAddress, advertiseAddress,        blockManagerPort, numUsableCores)    // ================================7.创建BlockManagerMaster; ========================    val blockManagerMaster = new BlockManagerMaster(registerOrLookupEndpoint(      BlockManagerMaster.DRIVER_ENDPOINT_NAME,      new BlockManagerMasterEndpoint(rpcEnv, isLocal, conf, listenerBus)),      conf, isDriver)    // =========================创建BlockManager==================================================    // NB: blockManager is not valid until initialize() is called later.    // BlockManager负责对Block的管理,只有在BlockManager的痴实话方法initialize被调用之后,它才是有效的。    // Blockmanager作为存储系统的一部分。    val blockManager = new BlockManager(executorId, rpcEnv, blockManagerMaster,      serializerManager, conf, memoryManager, mapOutputTracker, shuffleManager,      blockTransferService, securityManager, numUsableCores)

4.BlockManager的初始化

 /**   * Initializes the BlockManager with the given appId. This is not performed in the constructor as   * the appId may not be known at BlockManager instantiation time (in particular for the driver,   * where it is only learned after registration with the TaskScheduler).    *    * 用给定的appId初始化BlockManager。这不是在构造函数中执行的,因为appId在BlockManager实例化的时候    * (特别是对于驱动程序driver,只有在任务调度程序TaskScheduler注册后才会知道)的情况下是不知道的。   *   * This method initializes the BlockTransferService and ShuffleClient, registers with the   * BlockManagerMaster, starts the BlockManagerWorker endpoint, and registers with a local shuffle   * service if configured.    *    * 此方法初始化BlockTransferService和ShuffleClient,使用BlockManagerMaster注册,    * 启动BlockManagerWorker endpoint,并在注册一个本地的shuffle服务,如果配置了的话。    *    * BlockManager要生效,必须初始化,初始化步骤如下:    * 1.BlockTransService的初始化和ShuffleClient的初始化。ShuffleClient默认是BlockTransferService,    *   当有外部的ShuffleServer时,调用外部ShuffleServer的初始化方法。    * 2.BlockManagerId和ShuffleServiceId的创建。当有外部的ShuffleService时,创建新的BlockManagerId,    *   否则ShuffleServerId默认使用当前的BlockManager的BlockManagerId.    * 3.向BlockManagerMaster注册BlockmanagerId。   */  def initialize(appId: String): Unit = {    blockTransferService.init(this)    // 默认是BlockTransferService,这里有个疑问,这里在执行那个方法的初始化呢?点不开    shuffleClient.init(appId)    blockReplicationPolicy = {      val priorityClass = conf.get(        "spark.storage.replication.policy", classOf[RandomBlockReplicationPolicy].getName)      val clazz = Utils.classForName(priorityClass)      val ret = clazz.newInstance.asInstanceOf[BlockReplicationPolicy]      logInfo(s"Using $priorityClass for block replication policy")      ret    }    //一个blockManager对应一个executorId,blockTransferService的host,port    // 这一点使用了apply方法初始化的    val id =      BlockManagerId(executorId, blockTransferService.hostName, blockTransferService.port, None)    /**      * 这里是Executor中的BlockManager初始化的时候,向Driver中的BlockManagerMaster注册,此时BlockManagerMaster会      * 创建BlockManagerInfo来进行元数据管理      *      * slaveEndpoint:创建BlockManagerSlaveEndpoint这个消息循环体来接受Driver中的BlockManagerMaster发过来的指令,      * 例如删除Block等.使用BlockManagerSlaveEndpoint这个类;      * */    val idFromMaster = master.registerBlockManager(      id,      maxOnHeapMemory,      maxOffHeapMemory,      slaveEndpoint)    // 如果BlockManager向BlockManagerMaster注册成功,就返回更新后的ID,否则就是没更新前的ID    blockManagerId = if (idFromMaster != null) idFromMaster else id    // 当有外部的ShuffleService时,创建新的BlockManagerId,否则使用当前BlockManager的BlockManagerId    // 这里externalShuffleServiceEnabled默认为false    shuffleServerId = if (externalShuffleServiceEnabled) {      logInfo(s"external shuffle service port = $externalShuffleServicePort")      BlockManagerId(executorId, blockTransferService.hostName, externalShuffleServicePort)    } else {      blockManagerId    }    // 当有外部的ShuffleService且是Executor的BlockManager时,还需要向BlockManagerMaster注册ShuffleServerId    // Register Executors' configuration with the local shuffle service, if one should exist.    if (externalShuffleServiceEnabled && !blockManagerId.isDriver) {      registerWithExternalShuffleServer()    }    logInfo(s"Initialized BlockManager: $blockManagerId")  }