HBase createTable 的服务器端实现源码分析

HBase的所有请求调用都是通过RPC的机制进行的,RPCServer监听到请求之后会解析请求内容,然后根据解析的方法以及参数调用服务器端实际的方法,这也是远程代理模式的经典做法,createTable的请求最终实现是在HMaster中的,但是实际的表的建立过程是在CreateTableHandler类中的,接下来主要就HBase中表的建立过程进行详细分析。

1. HMaster的createTable实现

如下代码所示,是HMaster中的createTable的流程代码:

 public void createTable(HTableDescriptor hTableDescriptor,
                            byte[][] splitKeys) throws IOException {
        if (isStopped()) {
            throw new MasterNotRunningException();
        }
String namespace = hTableDescriptor.getTableName().getNamespaceAsString();
        ensureNamespaceExists(namespace);

        HRegionInfo[] newRegions = getHRegionInfos(hTableDescriptor, splitKeys);
        checkInitialized();
        sanityCheckTableDescriptor(hTableDescriptor);
        if (cpHost != null) {
            cpHost.preCreateTable(hTableDescriptor, newRegions);
        }
        LOG.info(getClientIdAuditPrefix() + " create " + hTableDescriptor);
        this.service.submit(new CreateTableHandler(this,
                this.fileSystemManager, hTableDescriptor, conf,
                newRegions, this).prepare());
        if (cpHost != null) {
            cpHost.postCreateTable(hTableDescriptor, newRegions);
        }

    }

在正式创建表之前做的几件事情:

1.检查Master是否正常运行

2.检查索要创建的表的namespace是否存在

3.HRegionInfo类包含了HRegion的相关信息getHRegionInfos(),函数按照splitKeys和表描述信息,获取该表对应的HRegion的信息。

这里有必要解释一下HRegionHRegion存储了table的数据信息,它包含了每一个row的所有columns,一个table包含1到多个hregion,每一个hregion包含多个HStores,每个HStores包含一部分的Rows和对应部分的Columns。

每个HRegion包含了一个[startKey, endKey),用来标识其保存的row的范围,英雌HRegion可以由TableNamekey range唯一确定

4.检查Master是否完成初始化

5.检查表信息是否符合规定

6.建表,建表又分为三个过程:

1. cpHost.preCreateTable(hTableDescriptor, newRegions);
2. submit(new CreateTableHandler(this,
            this.fileSystemManager, hTableDescriptor, conf,
            newRegions, this)
3.cpHost.postCreateTable(hTableDescriptor, newRegions);

其中步骤1和3都是为了协处理器预留的钩子函数,方便应用开发人员动态添加新的功能。

接下来主要分析一下步骤2中的建表所做的操作

2. CreateTableHandler 中的建表实现

其实在代码this.service.submit(new CreateTableHandler(this,

this.fileSystemManager, hTableDescriptor, conf,

newRegions, this).prepare());中调用的过程分为两个部分,一个是prepare,然后才是submit,先来看一下prepare()的工作

2.1 建表之前的准备工作prepare()分析

  public CreateTableHandler prepare()
      throws NotAllMetaRegionsOnlineException, TableExistsException, IOException {
    // Need hbase:meta availability to create a table
    try {
      if (server.getMetaTableLocator().waitMetaRegionLocation(
          server.getZooKeeper(), timeout) == null) {
        throw new NotAllMetaRegionsOnlineException();
      }
      // If we are creating the table in service to an RPC request, record the
      // active user for later, so proper permissions will be applied to the
      // new table by the AccessController if it is active
      if (RequestContext.isInRequestContext()) {
        this.activeUser = RequestContext.getRequestUser();
      } else {
        this.activeUser = UserProvider.instantiate(conf).getCurrent();
      }
    }
    //acquire the table write lock, blocking. Make sure that it is released.
    this.tableLock.acquire();
    boolean success = false;
    try {
      TableName tableName = this.hTableDescriptor.getTableName();
      if (MetaTableAccessor.tableExists(this.server.getConnection(), tableName)) {
        throw new TableExistsException(tableName);
      }

      checkAndSetEnablingTable(assignmentManager, tableName);
      success = true;
    } finally {
      if (!success) {
        releaseTableLock();
      }
    }
    return this;
  }

这里的主要工作如下:

1. 获取hbase:meta 信息,meta是hbase的一个特殊表,其存数了HBase上面的RegionServer的信息以及其分布情况。

2. 检查创建表的用户的权限并记录。

3. 获取table write锁

4. 检查表是否存在,已存在则抛出异常

5. 为了防止多个线程发起建同一个表的情况,可以在建表未成功之前可以先设置该table enable,这样其他线程就不能再建表。

建表之前的准备工作到此结束,一下分析具体建表流程

2.2 建表具体实现handleCreateTable过程分析

handleCreateTable,其实主要做了三件事,1.在磁盘上建表,2.meta表,3.为新建的表分配对应的regionserver。详细代码如下:

这块的代码是分为八个小步骤,我们一一分析,

1.创建表描述符

// 1. Create Table Descriptor
Path tempTableDir = FSUtils.getTableDir(tempdir, tableName);
new FSTableDescriptors(this.conf).createTableDescriptorForTableDirectory(
tempTableDir, this.hTableDescriptor, false);
Path tableDir = FSUtils.getTableDir(fileSystemManager.getRootDir(), tableName);

首先创建一个临时的文件夹,然后创建对应的文件表描述符,最后创建该表在文件系统中的路径,

HBase的表的数据对应在文件系统中的一个文件夹下,该文件夹也就是表名

2.创建Regions

// 2. Create Regions
List<HRegionInfo> regionInfos = handleCreateHdfsRegions(tempdir, tableName);

为table 创建in-disk数据结构,内部具体创建了存储table数据的HRegion,并返回hregioninfo的信息

3.将步骤1中的临时文件夹移到HBase的根目录下,如果hregions创建成功的话,继续一下几个步骤:

if (regionInfos != null && regionInfos.size() > 0) {
// 4. Add regions to META
    addRegionsToMeta(regionInfos);
// 5. Add replicas if needed
    regionInfos = addReplicas(hTableDescriptor, regionInfos);
// 6. Trigger immediate assignment of the regions in round-robin fashion
    ModifyRegionUtils.assignRegions(assignmentManager, regionInfos);
}
  1. 将新建的hregion信息注册到hbase的meta表中;
  2. 有必要的话创建这些hregion的副本
  3. 为新建的hregions分配对应的regionserver
  4. 在zookeeper中将新建的table设置为enable状态:
// 7. Set table enabled flag up in zk.
try {
        assignmentManager.getTableStateManager().setTableState(tableName,
        ZooKeeperProtos.Table.State.ENABLED);
    } catch (CoordinatedStateException e) {
      throw new IOException("Unable to ensure that " + tableName + " will be" +
        " enabled because of a ZooKeeper issue", e);
    }

8.跟新tabledescripter cache

// 8. Update the tabledescriptor cache.
((HMaster) this.server).getTableDescriptors().get(tableName);

至此服务器端数据库表的建立过程源码分析结束

时间: 2024-10-20 18:01:05

HBase createTable 的服务器端实现源码分析的相关文章

TeamTalk源码分析(七) —— 服务器端msf源码分析

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> TeamTalk源码分析(七) -- 服务器端msf源码分析 - 左雪菲的专栏 - 博客频道 - CSDN.NET 左雪菲的专栏 欢迎访问我的个人网站:http://www.hootina.org 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &n

传奇源码分析-客户端(游戏逻辑处理源分析五 服务器端响应)

器执行流程:(玩家走动) GameSrv服务器ProcessUserHuman线程处理玩家消息:遍历UserInfoList列表,依次调用每个UserInfo的Operate来处理命令队列中的所有操作; pUserInfo->Operate()调用m_pxPlayerObject->Operate()调用.判断玩家if (!m_fIsDead),如果已死,则发送_MSG_FAIL消息.我们在前面看到过,该消息是被优先处理的.否则则调用WalkTo,并发送_MSG_GOOD消息给客户端.Walk

Hbase写入hdfs源码分析

版权声明:本文由熊训德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/258 来源:腾云阁 https://www.qcloud.com/community 本文档从源码角度分析了,hbase作为dfs client写入hdfs的hadoop sequence文件最终刷盘落地的过程.之前在<wal线程模型源码分析>中描述wal的写过程时说过会写入hadoop sequence文件,hbase为了保证数据的安全性,一般都

hbase split 源码分析之split策略

在工作中接触到split,于是查看了这块的源代码,先看到了split的策略,今天就说说这个吧,后续还会有split的其他源码分析和compact相关的源码分析. 看了很多其他人的博客,很多都是转发的,原创的也都没有注明是哪个版本.其实给很多读者造成混淆,我这里是基于Hbase-0.98.13  版本作为分析的,注意:不同版本的此部分源码很可能不一样. 在这个版本中使用的split策略是IncreasingToUpperBoundRegionSplitPolicy.确切来说他是0.94版本以后的策

hbase(0.94) get、scan源码分析

简介 本文是需要用到hbase timestamp性质时研究源码所写.内容有一定侧重.且个人理解不算深入,如有错误请不吝指出. 如何看源码 hbase依赖很重,没有独立的client包.所以目前如果在maven中指定如下: <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase</artifactId> <version>0.94-adh3u9.9</

Spark SQL之External DataSource外部数据源(二)源码分析

上周Spark1.2刚发布,周末在家没事,把这个特性给了解一下,顺便分析下源码,看一看这个特性是如何设计及实现的. /** Spark SQL源码分析系列文章*/ (Ps: External DataSource使用篇地址:Spark SQL之External DataSource外部数据源(一)示例 http://blog.csdn.net/oopsoom/article/details/42061077) 一.Sources包核心 Spark SQL在Spark1.2中提供了External

hadoop源码分析解读入门

hadoop 源代码分析(一) Google 的核心竞争技术是它的计算平台.HadoopGoogle的大牛们用了下面5篇文章,介绍了它们的计算设施. Google的几篇论文 GoogleCluster:http://research.google.com/archive/googlecluster.html Chubby:http://labs.google.com/papers/chubby.html GFS:http://labs.google.com/papers/gfs.html Big

HBase1.0.0源码分析之请求处理流程分析以Put操作为例(一)

如下面的代码所示,是HBase Put操作的简单代码实例,关于代码中的Connection connection = ConnectionFactory.createConnection(conf),已近在前一篇博 HBase1.0.0源码分析之Client启动连接流程,中介绍了链接的相关流程以及所启动的服务信息. TableName tn = TableName.valueOf("test010"); try (Connection connection = ConnectionFa

第十一篇:Spark SQL 源码分析之 External DataSource外部数据源

上周Spark1.2刚发布,周末在家没事,把这个特性给了解一下,顺便分析下源码,看一看这个特性是如何设计及实现的. /** Spark SQL源码分析系列文章*/ (Ps: External DataSource使用篇地址:Spark SQL之External DataSource外部数据源(一)示例 http://blog.csdn.net/oopsoom/article/details/42061077) 一.Sources包核心 Spark SQL在Spark1.2中提供了External