HBase createTable 的伺服器端實現源碼分析,hbasecreatetable

來源:互聯網
上載者:User

HBase createTable 的伺服器端實現源碼分析,hbasecreatetable

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 DescriptorPath 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 RegionsList<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);}
// 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);

至此伺服器端資料庫表的建立過程源碼分析結束

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.