HBase 1.2.0源码系列:HMaster启动

HMaster 启动类 org.apache.hadoop.hbase.master.HMaster,HMaster 继承了 HRegionServer,实现了 MasterServices。

类描述:HMaster 可以运行多个,通过 Zookeeper 选出一个 Active Master,其他 HMaster 会阻塞在构造方法中,直到集群 shutdown 或 active master 丢失(An HBase cluster has one active master. If many masters are started, all compete. Whichever wins goes on to run the cluster. All others park themselves in their constructor until master or cluster shutdown or until the active master loses its lease in zookeeper)

0. HMaster 初始化

a. 初始化以下信息:
Fatal error 缓存、Replication 信息、 压缩和加密信息(HBASE-6370)、HMaster 指标监控、表描述符(默认预加载)
b. 服务状态的推送(默认不开启),hbase.status.publisher.class 指定状态推送实现类
c. 启动内嵌的 JettyServer,默认监听 “0.0.0.0:16010” 端口,可以通过 Web 的方式访问 HMaster 的信息
d. 启动 ActiveMasterManager,连接ZK进行 Master 选举,如果不是 Master 的话,就一直阻塞。

public HMaster(final Configuration conf, CoordinatedStateManager csm)
      throws IOException, KeeperException, 
      InterruptedException {
    
    // 存放来自 region server 的 fatal error 信息,超过 buffer 大小后会自动清理
    this.rsFatals = new MemoryBoundedLogMessageBuffer(
      conf.getLong("hbase.master.buffer.for.rs.fatals", 1*1024*1024));

    // Disable usage of meta replicas in the master
    this.conf.setBoolean(HConstants.USE_META_REPLICAS, false);

    // 初始化 Replication 信息
    Replication.decorateMasterConfiguration(this.conf);

    // 初始化 HMaster 的压缩和加密信息
    this.masterCheckCompression = conf.getBoolean("hbase.master.check.compression", true);
    this.masterCheckEncryption = conf.getBoolean("hbase.master.check.encryption", true);

    // Metrics for HMaster
    this.metricsMaster = new MetricsMaster(new MetricsMasterWrapperImpl(this));

    // 预加载表描述(Schema)
    this.preLoadTableDescriptors = conf.getBoolean("hbase.master.preload.tabledescriptors", true);

    // ..

    // ZK监控
    activeMasterManager = new ActiveMasterManager(zooKeeper, this.serverName, this);
    
    // 启动内嵌的 JettyServer,默认监听 "0.0.0.0:16010" 端口,可以通过 Web 的方式访问 HMaster 的信息
    int infoPort = putUpJettyServer();

    // 选举 Master
    startActiveMasterManager(infoPort);

}

 

1. 选举成为 Master 后会调用 finishActiveMasterInitialization

创建监控 HMaster 线程(InitializationMonitor),初始化以下对象或操作:

private void finishActiveMasterInitialization(MonitoredTask status)
      throws IOException, InterruptedException, KeeperException, 
      CoordinatedStateException {

    isActiveMaster = true;

    // 监控线程
    Thread zombieDetector = new Thread(new InitializationMonitor(this));
    zombieDetector.start();

    // 包装 HDFS 操作
    this.fileSystemManager = new MasterFileSystem(this, this);

    // 设置 meta 表的 Replication
    this.tableDescriptors.get(TableName.META_TABLE_NAME)
      .setRegionReplication(
        conf.getInt(HConstants.META_REPLICAS_NUM, HConstants.DEFAULT_META_REPLICA_NUM));

    // 加载表 Schema 信息,从 HDFS 上读取
    if (preLoadTableDescriptors) {
        this.tableDescriptors.getAll();
    }

    // 创建 ServerManager,管理 region server
    this.serverManager = createServerManager(this, this);

    // 提供访问集群里所有 server 的方式
    setupClusterConnection();

    // 清除表级别的 write lock
    this.tableLockManager.reapWriteLocks();

    // 初始化一系列监控ZK的对象,详细见下文
    initializeZKBasedSystemTrackers();

    // 在处理请求前,初始化 master side coprocessors
    // 提供 Coprocessor 的运行环境
    this.cpHost = new MasterCoprocessorHost(this, this.conf);

    // 启动 HMaster 处理任务的线程池
    // MASTER_CLOSE_REGION hbase.master.executor.openregion.threads
    // MASTER_OPEN_REGION hbase.master.executor.closeregion.threads
    // MASTER_SERVER_OPERATIONS hbase.master.executor.serverops.threads
    // MASTER_META_SERVER_OPERATIONS hbase.master.executor.serverops.threads
    // M_LOG_REPLAY_OPS hbase.master.executor.logreplayops.threads
    // MASTER_TABLE_OPERATIONS 1
    startServiceThreads();

    // 等待 RegionServer 的汇报
    // 1. 向 HMaster 汇报的 RegionServer 数量达到hbase.master.wait.on.regionservers.maxtostart(Integer.MAX_VALUE)
    // 2. 向 HMaster 汇报的 RegionRerver 数量达到hbase.master.wait.on.regionservers.mintostart(1),
    // 并且等待时间超过 hbase.master.wait.on.regionservers.timeout(4500ms)
    // 同时在 hbase.master.wait.on.regionservers.interval(1500ms)内向 HMaster 注册的 RegionServer 数量没有变
    // 在同时满足以上条件后结束等待
    this.serverManager.waitForRegionServers(status);

    // 检查在ZK当中注册了,但是没在 HMaster 这里注册的 RegionServer
    for (ServerName sn: this.regionServerTracker.getOnlineServers()) {
        // 只输出日志,不处理
    }

    // ... 分配 meta region
}

 

1.1 initializeZKBasedSystemTrackers 创建以下对象:

// region balancer,控制 RegionServer 负载
// 返回 RegionPlan(Region 应该放在哪个 RegionServer 上)
// 默认为 StochasticLoadBalancer
this.balancer = LoadBalancerFactory.getLoadBalancer(conf);

// 用于 Region 的 split 和 merge 使得一个 table 的所有 region 的大小趋于均衡
// 默认为 SimpleRegionNormalizer
this.normalizer = RegionNormalizerFactory.getRegionNormalizer(conf);

// 监听 load balancer 状态
// ZK节点 /hbase/balancer(zookeeper.znode.balancer)
this.loadBalancerTracker = new LoadBalancerTracker(zooKeeper, this);

// 监听 region normalizer 状态
// ZK节点 /hbase/normalizer(zookeeper.znode.regionNormalizer)
this.regionNormalizerTracker = new RegionNormalizerTracker(zooKeeper, this);

// 负责 Assign Region,RPC 通知 RegionServer 执行 open region 操作
// 这里能找到 RIT 的 Region
// 监听 /hbase/region-in-transition 节点(zookeeper.znode.unassigned)
this.assignmentManager = new AssignmentManager(this, serverManager,
this.balancer, this.service, this.metricsMaster,
this.tableLockManager);

// 监听 RegionServer 的状态
// ZK节点 /hbase/rs(zookeeper.znode.rs)
this.regionServerTracker = new RegionServerTracker(zooKeeper, this,
this.serverManager);

// 监听 RegionServer(下线的) 的状态
// ZK节点 /hbase/draining(zookeeper.znode.draining.rs)
this.drainingServerTracker = new DrainingServerTracker(zooKeeper, this,
this.serverManager);

// 监听 cluster 是否正常运行
// ZK节点 /hbase/running(zookeeper.znode.state)的内容为当前 HMaster 的信息
boolean wasUp = this.clusterStatusTracker.isClusterUp();
if (!wasUp) this.clusterStatusTracker.setClusterUp();

// 注册 SnapshotManager、MasterFlushTableProcedureManager 和其他 ProcedureManager
// Procedure 负责处理对 table 的创建、修改、Flush 等操作
// mpmHost 提供 Procedure 的运行环境
this.snapshotManager = new SnapshotManager();
this.mpmHost = new MasterProcedureManagerHost();
this.mpmHost.register(this.snapshotManager);
this.mpmHost.register(new MasterFlushTableProcedureManager());
this.mpmHost.loadProcedures(conf);

 

2. 在初始化了各种对象后,需要分配  meta 表

在此之前,恢复 meta 表,对 failed server 上的 meta region 执行 split log

private void finishActiveMasterInitialization(MonitoredTask status)
      throws IOException, InterruptedException, KeeperException, 
      CoordinatedStateException {
    // ...

    // 注释:在 Master 启动过程中会恢复 meta region server
    // 其他失败的 region server 建议通过 SSH 处理会尽可能快速启动 Master

    // 从 WALs 目录下找出之前失败的 region server
    // HDFS 目录 /hbase/WALs 下每一个 RegionServer 有一个子目录,从 /hbase/WALs 中解析出所有的 region server
    // 不在 onlineServers 中的即认为是失败的 
    Set<ServerName> previouslyFailedServers =
    this.fileSystemManager.getFailedServersFromLogFolders();

    // log splitting for hbase:meta server
    // 获得 meta region 所在的 RegionServer
    // ZK节点 /hbase/meta-region-server 存储之前 meta region 所在的 server
    ServerName oldMetaServerLocation = metaTableLocator.getMetaRegionLocation(this.getZooKeeper());

    // 如果之前 meta region 所在的 server 在 failed server 列表中,则认为 meta region 需要恢复
    if (oldMetaServerLocation != null && previouslyFailedServers.contains(oldMetaServerLocation)) {
        // 执行 split meta log
        splitMetaLogBeforeAssignment(oldMetaServerLocation);
    }

    // ...
}

private void splitMetaLogBeforeAssignment(ServerName currentMetaServer)
      throws IOException {

    // hbase.master.distributed.log.replay 属性,默认是 false,即通过 split log 恢复
    // RecoveryMode 是 LOG_REPLAY(日志重放),将 meta region 放到ZK的 /hbase/recovering-regions 下
    if (RecoveryMode.LOG_REPLAY == this.getMasterFileSystem().getLogRecoveryMode()) {
        Set<HRegionInfo> regions = new HashSet<HRegionInfo>();
        regions.add(HRegionInfo.FIRST_META_REGIONINFO);
        this.fileSystemManager.prepareLogReplay(currentMetaServer, regions);
    }

    // RecoveryMode 是 LOG_SPLITTING(日志切分),将 meta region 所在的failed region server 的 WAL log 做 split log 操作
    else {
        this.fileSystemManager.splitMetaLog(currentMetaServer);
    }
}

 

2.1 调用 splitLog 方法执行 split 日志的操作

public void splitLog(final Set<ServerName> serverNames, PathFilter filter)
      throws IOException {
    long splitTime = 0, splitLogSize = 0;
    // 修改 WALs 日志目录的名称,在需要 split 的目录的名称后面加上.splitting
    List<Path> logDirs = getLogDirs(serverNames);

    // splitLogManager 记录 dead server 列表
    splitLogManager.handleDeadWorkers(serverNames);

    // 执行 split 日志
    splitLogSize = splitLogManager.splitLogDistributed(serverNames, logDirs, filter);

    // 记录 split 结果到 MetricsMaster 当中
    // 使用 path filter 区分 META 表和普通表,META 表的日志以.meta结尾
    if (this.metricsMasterFilesystem != null) {
        if (filter == META_FILTER) {
            this.metricsMasterFilesystem.addMetaWALSplit(splitTime, splitLogSize);
        } else {
            this.metricsMasterFilesystem.addSplit(splitTime, splitLogSize);
        }
    }
}

/**
* 执行 Split log
* 在所有指定 region server 的 META 表日志处理结束(成功或失败)前阻塞
* @param logDirs List of log dirs to split
* @param filter the Path filter to select specific files for considering
* @return cumulative size of the logfiles split
*/
public long splitLogDistributed(final Set<ServerName> serverNames, final List<Path> logDirs,
      PathFilter filter) throws IOException {

    FileStatus[] logfiles = getFileList(logDirs, filter);

    // ...

    // 统计任务完成结果
    TaskBatch batch = new TaskBatch();
    Boolean isMetaRecovery = (filter == null) ? null : false;
    for (FileStatus lf : logfiles) {
        String pathToLog = FSUtils.removeRootPath(lf.getPath(), conf);

        // 把任务插入到 Split 任务列表当中
        // 在ZK节点 /hbase/splitWAL 下创建原来的相对路径名加密编码后的值
        if (!enqueueSplitTask(pathToLog, batch)) {
            throw new IOException("duplicate log split scheduled for " + lf.getPath());
        }
    }

    // 等待任务结束
    // RegionServer 会有 SplitLogWorker 读取ZK节点 /hbase/splitWAL 处理 split
    // 参考 SplitLogWorker.splitLogFile
    waitForSplittingCompletion(batch, status);

    // remove recovering regions
    if (filter == MasterFileSystem.META_FILTER) {
        isMetaRecovery = true;
    }
    // 清理 recovering 的状态
    // region server 不让访问 recovering 状态的 region
    removeRecoveringRegions(serverNames, isMetaRecovery);

    if (batch.done != batch.installed) {
        // 启动的任务和完成的任务不相等的情况
        // ... 记录异常
        throw new IOException(msg);
    }

    // 清理 split 前的 log 目录
    for (Path logDir : logDirs) {

        final FileSystem fs = logDir.getFileSystem(conf);
        try {
            if (fs.exists(logDir) && !fs.delete(logDir, false)) {
                // ...
            }
        } catch (IOException ioe) {
            // ...
        }
    }

    return totalSize;
}

 

2.2 分配 meta 表,调用 assignMeta

void assignMeta(MonitoredTask status, Set<ServerName> previouslyFailedMetaRSs, int replicaId)
      throws InterruptedException, IOException, KeeperException {
    // Work on meta region
    int assigned = 0;

    RegionStates regionStates = assignmentManager.getRegionStates();
    // 从ZK节点 /hbase/meta-region-server 获取当前 meta state
    RegionState metaState = MetaTableLocator.getMetaRegionState(getZooKeeper(), replicaId);

    // meta 表第一个 region
    HRegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(HRegionInfo.FIRST_META_REGIONINFO,
        replicaId);
    ServerName currentMetaServer = metaState.getServerName();

    // Add a region to RegionStates
    if (!ConfigUtil.useZKForAssignment(conf)) {
        regionStates.createRegionState(hri, metaState.getState(),
            currentMetaServer, null);
    } else {
        regionStates.createRegionState(hri);
    }

    // If region is up in zk in transition, then do fixup and block and wait until
    // the region is assigned and out of transition.
    // 处理 meta 表第一个 region
    boolean rit = this.assignmentManager.
    processRegionInTransitionAndBlockUntilAssigned(hri);
    // 在 timeout 时间内等待 hbase:meta 表是否可以被访问
    boolean metaRegionLocation = metaTableLocator.verifyMetaRegionLocation(
        this.getConnection(), this.getZooKeeper(), timeout, replicaId);

    if (!metaRegionLocation || !metaState.isOpened()) {
        // Meta location is not verified. It should be in transition, or offline.
        // We will wait for it to be assigned in enableSSHandWaitForMeta below.
        if (!ConfigUtil.useZKForAssignment(conf)) {
            assignMetaZkLess(regionStates, metaState, timeout, previouslyFailedMetaRSs);
        } else if (!rit) {
            // 重新执行之前的 split log 操作
            if (currentMetaServer != null) {
                if (serverManager.isServerOnline(currentMetaServer)) {
                    serverManager.expireServer(currentMetaServer);
                }
                if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
                    splitMetaLogBeforeAssignment(currentMetaServer);
                    previouslyFailedMetaRSs.add(currentMetaServer);
                }
            }

            // 重新 assign 一次 meta 表
            assignmentManager.assignMeta(hri);
        }
    }

    else {
        // assign 成功,更新状态为 online
        regionStates.updateRegionState(
            HRegionInfo.FIRST_META_REGIONINFO, State.OPEN, currentMetaServer);
        this.assignmentManager.regionOnline(
            HRegionInfo.FIRST_META_REGIONINFO, currentMetaServer);
    }

    // ZK中设置 meta 表启用状态
    if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) enableMeta(TableName.META_TABLE_NAME);

    // ...

}

在 AssignmentManager 中调用 assign,向 RegionServer 发请求 open region

regionOpenState = serverManager.sendRegionOpen(
    plan.getDestination(), region, versionOfOfflineNode, favoredNodes);

 

3. 恢复其他 region

回到 finishActiveMasterInitialization 方法中,对 dead server 进行处理

// previouslyFailedServers 是之前判断出来的 dead server
for (ServerName tmpServer : previouslyFailedServers) {
    // 将这些 server 保存起来,master 不会等待他们都恢复完再继续
    this.serverManager.processDeadServer(tmpServer, true);
}

恢复这些 region 的过程比较慢,涉及到 WAL log split 和 region assign,Master 不会等待他们恢复

 

分配 region 的工作都是由 AssignmentManager 来完成的,调用 assignmentManager.joinCluster()

// 如果是新启动的,就分配所有的用户 region
// 如果是 failover 的情况,就修复 assignmentManager 当中有问题的 region 状态,
void joinCluster() throws IOException,
      KeeperException, InterruptedException, CoordinatedStateException {
    long startTime = System.currentTimeMillis();

    // 获得 dead server 列表
    // Scan hbase:meta 表构建 region、server和 assignment 列表
    // replicasToClose 保存需要重新 assign 的 region(merge 和 split 状态的region)
    // offlineServers 保存 dead server(region 所在 server 不在 onlineServer)
    Set<ServerName> deadServers = rebuildUserRegions();

    // 处理 deadServer 和正在 merge 或 transition 没有完成的 region
    // 在方法里要判断是否是 failover 的情况
    boolean failover = processDeadServersAndRegionsInTransition(deadServers);

    // 清除ZK节点 /hbase/region-in-transition(zookeeper.znode.unassigned)
    if (!useZKForAssignment) {
        ZKUtil.deleteNodeRecursively(watcher, watcher.assignmentZNode);
    }

    // 恢复在 Enabling 和 Disabling 状态的表
    recoverTableInDisablingState();
    recoverTableInEnablingState();
}

 

3.1 processDeadServersAndRegionsInTransition 方法

主要逻辑用于判断是否是 failover 情况

// Process all regions that are in transition in zookeeper and also
// processes the list of dead servers.
boolean processDeadServersAndRegionsInTransition(final Set<ServerName> deadServers)
      throws KeeperException, IOException, InterruptedException, 
      CoordinatedStateException {

    // 读ZK的节点 /hbase/region-in-transition 获取需要 assignment 的 region
    List<String> nodes = ZKUtil.listChildrenNoWatch(watcher, watcher.assignmentZNode);

    // serverManager 里有 deadServer
    boolean failover = !serverManager.getDeadServers().isEmpty();
    if (failover) {
        // ...
    } else {
        // 如果除了 meta region 外有 region 是 assigned 状态,是 failover
        Set<ServerName> onlineServers = serverManager.getOnlineServers().keySet();
        for (Map.Entry<HRegionInfo, ServerName> en:
              regionStates.getRegionAssignments().entrySet()) {
            HRegionInfo hri = en.getKey();
            if (!hri.isMetaTable()
              && onlineServers.contains(en.getValue())) {
                failover = true;
                break;
            }
        }
        if (!failover && nodes != null) {
            // 如果除了 meta region 外有 region 是 RIT 状态(split 或者 merge 还没有完成的 region)是 failover
            for (String encodedName: nodes) {
                RegionState regionState = regionStates.getRegionState(encodedName);
                if (regionState != null && !regionState.getRegion().isMetaRegion()) {
                    failover = true;
                    break;
                }
            }
        }
    }

    if (!failover && !useZKForAssignment) {
        // 如果除了 meta region 外有 region 是 RIT 状态(split 或者 merge 还没有完成的 region)是 failover
        Map<String, RegionState> regionsInTransition = regionStates.getRegionsInTransition();
        if (!regionsInTransition.isEmpty()) {
            Set<ServerName> onlineServers = serverManager.getOnlineServers().keySet();
            for (RegionState regionState: regionsInTransition.values()) {
                ServerName serverName = regionState.getServerName();
                if (!regionState.getRegion().isMetaRegion()
                  && serverName != null && onlineServers.contains(serverName)) {
                    failover = true;
                    break;
                }
            }
        }
    }

    if (!failover) {
        // 如果 dead server 的 WALs 路径下有 splitting log,是 failover
        Set<ServerName> queuedDeadServers = serverManager.getRequeuedDeadServers().keySet();
        if (!queuedDeadServers.isEmpty()) {
            // ...
            for (ServerName serverName: queuedDeadServers) {
                // ...
                Path splitDir = logDir.suffix(DefaultWALProvider.SPLITTING_EXT);
                if (fs.exists(logDir) || fs.exists(splitDir)) {
                    failover = true;
                    break;
                }
            }

            if (!failover) {
                // 如果不是 failover,清除 dead server
                serverManager.removeRequeuedDeadServers();
            }
        }
    }

    Set<TableName> disabledOrDisablingOrEnabling = null;
    Map<HRegionInfo, ServerName> allRegions = null;

    if (!failover) {
        disabledOrDisablingOrEnabling = tableStateManager.getTablesInStates(
          ZooKeeperProtos.Table.State.DISABLED,
          ZooKeeperProtos.Table.State.DISABLING,
          ZooKeeperProtos.Table.State.ENABLING);

        // mark all user regions closed before reassignment
        allRegions = regionStates.closeAllUserRegions(
          disabledOrDisablingOrEnabling);
    }

    // Now region states are restored
    regionStateStore.start();

    if (failover) {
        // 如果是 failover,处理 dead server 和 RIT
        // dead server 通过 ServerCrashProcedure 异步完成
        // region in transition 同步完成
        // See HBASE-4580 for more information.
        processDeadServersAndRecoverLostRegions(deadServers);
    }

    if (!failover && useZKForAssignment) {
        // 清除ZK监听,并启动新的监听
        ZKAssign.deleteAllNodes(watcher);
        ZKUtil.listChildrenAndWatchForNewChildren(this.watcher,
        this.watcher.assignmentZNode);
    }

    if (!failover) {
        // assign 所有的 regions
        assignAllUserRegions(allRegions);
    }

    // ...
}

 

3.2 异步 assign region

private void assign(int regions, int totalServers,
      String message, Map<ServerName, List<HRegionInfo>> bulkPlan)
      throws InterruptedException, IOException {

    int servers = bulkPlan.size();

    // hbase.bulk.assignment.threshold.regions
    // hbase.bulk.assignment.threshold.servers
    // 如果 region 数量或着 server 数量超过阈值,使用 bulk assign
    if (servers == 1 || (regions < bulkAssignThresholdRegions
      && servers < bulkAssignThresholdServers)) {
        // 小集群下效率更高
        ArrayList<HRegionInfo> userRegionSet = new ArrayList<HRegionInfo>(regions);
        for (Map.Entry<ServerName, List<HRegionInfo>> plan: bulkPlan.entrySet()) {
            if (!assign(plan.getKey(), plan.getValue())) {
                for (HRegionInfo region: plan.getValue()) {
                    if (!regionStates.isRegionOnline(region)) {
                        // 异步 assign
                        // 线程池中调用 assignmentManager.assign(hri, true, newPlan);
                        // 线程池大小 hbase.assignment.threads.max,默认30
                        invokeAssign(region);
                    }
                }
            }
        }

        // 等待 assignment 完成
        // 等待时间 hbase.bulk.assignment.perregion.open.time * (reassigningRegions + 1)
        if (!waitForAssignment(userRegionSet, true, userRegionSet.size(),
            System.currentTimeMillis())) {
            // ....
        }

    } else {
        // bulk assign
        // 使用 fixed 线程池 assign
        BulkAssigner ba = new GeneralBulkAssigner(
        this.server, bulkPlan, this, bulkAssignWaitTillAllAssigned);
        ba.bulkAssign();
    }
}

分配 user region 的方法和分配 meta region 的过程基本一致。

4. 开启一系列调度,由 choreService 执行

// master.getClusterStatus()
// 获取 clusterStatus,用于 loadBalancer 决定 assign region 到哪个 server 上
this.clusterStatusChore = new ClusterStatusChore(this, balancer);
getChoreService().scheduleChore(clusterStatusChore);

// master.balance()
// 获得 RegionPlan(需要移动的 region info,source region server 和 dest region server)
// 只负责根据 clusterStatus 生成 RegionPlan,region 的迁移则是由 assignmentManager 根据 plan 完成
this.balancerChore = new BalancerChore(this);
getChoreService().scheduleChore(balancerChore);

// master.normalizeRegions()
// 使得一个 table 的所有 region 的大小趋于均衡
// split 过大的 region,merge 太小的 region
// 生成 NormalizationPlan(SplitNormalizationPlan、MergeNormalizationPlan、EmptyNormalizationPlan)
// AdminService 会发送 RPC 到某个 region server 让其对 region split 或者 merge
this.normalizerChore = new RegionNormalizerChore(this);
getChoreService().scheduleChore(normalizerChore);

// 对于被 merge 或 split 操作成为新 region
// 定期 scan meta table,如果新 region 不在持有旧 region 的 reference file
// 可以移除旧 region(HFile 移动到 HDFS 目录 /hbase/archive/{tableName}/{encoded-region-name} 路径下)
this.catalogJanitorChore = new CatalogJanitor(this, this);
getChoreService().scheduleChore(catalogJanitorChore);

5. 其他操作

// 创建 TableNamespaceManager,创建、访问、操作 namespace 的包装类
initNamespace();

// 创建 MasterQuotaManager,创建、访问、操作 quota 的包装类
initQuotaManager();

// 清除与 online server 有相同 host name 和 port 的dead server
// See HBASE-5916.
this.serverManager.clearDeadServersWithSameHostNameAndPortOfOnlineServer();

// Check and set the znode ACLs if needed in case we are overtaking a non-secure configuration
zooKeeper.checkAndSetZNodeAcls();
...

 

HMaster的主要启动流程如上所诉。欢迎补充和提出错误。

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

14 − 9 =