您的位置:首页 > 编程语言

hbase 源代码解析(4) 的createTable 的 region assign

2017-07-11 23:20 405 查看
上一章节主要推了一番createTable的服务器(HMaster)过程。

上一章节网址: http://blog.csdn.net/chenfenggang/article/details/74938045

中间留下了assign region的过程需要分析,以及在regionService中启动region

case CREATE_TABLE_ASSIGN_REGIONS:
assignRegions(env, getTableName(), newRegions);
setNextState(CreateTableState.CREATE_TABLE_UPDATE_DESC_CACHE);
break;


上一章节就是留下上面这个流程。这里包括region的分配以及open。

protected static void assignRegions(final MasterProcedureEnv env,
final TableName tableName, final List<HRegionInfo> regions)
throws HBaseException, IOException {
....
// Mark the table as Enabling
//assignmentManager 就是HMaster
//getTableStateManager 是zk的管理 。
assignmentManager.getTableStateManager().setTableState(tableName,
ZooKeeperProtos.Table.State.ENABLING);
// Trigger immediate assignment of the regions in round-robin fashion
ModifyRegionUtils.assignRegions(assignmentManager, regions);
// Enable table
assignmentManager.getTableStateManager()
.setTableState(tableName, ZooKeeperProtos.Table.State.ENABLED);
}


这里先将zk置为enabling,然后为regionservice分配region, 然后设置为enable

下面是setTableState 里调用的一个方法。

private void setTableStateInZK(final TableName tableName,
final ZooKeeperProtos.Table.State state)
throws KeeperException {
String znode = ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString());
if (ZKUtil.checkExists(this.watcher, znode) == -1) {
ZKUtil.createAndFailSilent(this.watcher, znode);
}
synchronized (this.cache) {
ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder();
builder.setState(state);
byte [] data = ProtobufUtil.prependPBMagic(builder.build().toByteArray());
ZKUtil.setData(this.watcher, znode, data);
this.cache.put(tableName, state); //缓存是为了方便查询。
}
}


ZKUtil.setData(this.watcher, znode, data); watcher 保留着zk的连接信息。

回到重点 ModifyRegionUtils.assignRegions(assignmentManager, regions);

public void assign(List<HRegionInfo> regions)
throws IOException, InterruptedException {
.....
List<ServerName> servers = serverManager.createDestinationServersList();
// Generate a round-robin bulk assignment plan
Map<ServerName, List<HRegionInfo>> bulkPlan = balancer.roundRobinAssignment(regions, servers);
....
processFavoredNodes(regions);
assign(regions.size(), servers.size(), "round-robin=true", bulkPlan);
}


如果反过去查找HMaster的初始过程,可以知道这个balancer 是StochasticLoadBalancer,继承了BaseLoadBalancer 。

这是里面的一段代码。

/**
* Round robin a list of regions to a list of servers
*/
private void roundRobinAssignment(Cluster cluster, List<HRegionInfo> regions,
List<HRegionInfo> unassignedRegions, List<ServerName> servers,
Map<ServerName, List<HRegionInfo>> assignments) {
int numServers = servers.size();
int numRegions = regions.size();
int max = (int) Math.ceil((float) numRegions / numServers);
int serverIdx = 0;
if (numServers > 1) {
serverIdx = RANDOM.nextInt(numServers);  //随机
}
int regionIdx = 0;
for (int j = 0; j < numServers; j++) {
ServerName server = servers.get((j + serverIdx) % numServers);
List<HRegionInfo> serverRegions = new ArrayList<HRegionInfo>(max);
for (int i = regionIdx; i < numRegions; i += numServers) {
HRegionInfo region = regions.get(i % numRegions);
if (cluster.wouldLowerAvailability(region, server)) {
unassignedRegions.add(region);
} else {
serverRegions.add(region);
cluster.doAssignRegion(region, server);
}
}
assignments.put(server, serverRegions);
regionIdx++;
}
}


这个就是将服务器重新洗牌的意思。将region平均分配到可用的server上

HRegionInfo 主要包含表的定义,startkey等。。

然后把计划实现一下。assign(regions.size(), servers.size(), “round-robin=true”, bulkPlan);

// invoke assignment (async)
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)) {
invokeAssign(region);
if (!region.getTable().isSystemTable()) {
userRegionSet.add(region);
}
}
}
}
}


采用同步方法,执行计划。

这时serviceManger会启动region 这个是由Hmaster 发往regionService的命令。在regionService里开启region

public RegionOpeningState sendRegionOpen(final ServerName server,
HRegionInfo region, int versionOfOfflineNode, List<ServerName> favoredNodes)
throws IOException {
AdminService.BlockingInterface admin = getRsAdmin(server);
if (admin == null) {
LOG.warn("Attempting to send OPEN RPC to server " + server.toString() +
" failed because no RPC connection found to this server");
return RegionOpeningState.FAILED_OPENING;
}
OpenRegionRequest request = RequestConverter.buildOpenRegionRequest(server,
region, versionOfOfflineNode, favoredNodes,
(RecoveryMode.LOG_REPLAY == this.services.getMasterFileSystem().getLogRecoveryMode()));
try {
OpenRegionResponse response = admin.openRegion(null, request);
return ResponseConverter.getRegionOpeningState(response);
} catch (ServiceException se) {
throw ProtobufUtil.getRemoteException(se);
}
}


到RegionService了通过regionInfo 可以获得你想要的很多信息。然后一番正确性确认。然后开启region

最终的最终调用了这个

Pair<HRegionInfo, ServerName> p = MetaTableAccessor.getRegion(
regionServer.getConnection(), region.getRegionName());
然后在meta里拿到regionLocation
/**
* Returns the HRegionLocation from meta for the given region
* @param connection connection we're using
* @param regionName region we're looking for
* @return HRegionLocation for the given region
* @throws IOException
*/
public static HRegionLocation getRegionLocation(Connection connection,
byte[] regionName) throws IOException {
byte[] row = regionName;
HRegionInfo parsedInfo = null;
try {
parsedInfo = parseRegionInfoFromRegionName(regionName);
row = getMetaKeyForRegion(parsedInfo);
} catch (Exception parseEx) {
// Ignore. This is used with tableName passed as regionName.
}
Get get = new Get(row);
get.addFamily(HConstants.CATALOG_FAMILY);
Result r = get(getMetaHTable(connection), get);//这里是采用META里拿数据。
RegionLocations locations = getRegionLocations(r);
return locations == null
? null
: locations.getRegionLocation(parsedInfo == null ? 0 : parsedInfo.getReplicaId());
}


而这里的meta在Hmaster的createtable的时候写入的。这样看来HMaster什么都做完了,region分配在那个regionServier上,regioninfo ,startkey等。包括HRegionLocation等信息都在Hmaster搞定

不信回头看看,第一 步就是创建regions,第二步就是写入METa数据表。

case CREATE_TABLE_WRITE_FS_LAYOUT:
newRegions = createFsLayout(env, hTableDescriptor, newRegions);
setNextState(CreateTableState.CREATE_TABLE_ADD_TO_META);
break;
case CREATE_TABLE_ADD_TO_META:
newRegions = addTableToMeta(env, hTableDescriptor, newRegions);
setNextState(CreateTableState.CREATE_TABLE_ASSIGN_REGIONS);
break;


这样整个createTable的流程结束。

同时也将 client->ZK ->HMaster->RegionService->Region 过程走了一回

同时几个RPC MasterRpcServices RSRPCService

学习挺多的。

下节将回到最开始的地方。Connetion里的getTable。分享一下get,put。scan,三个方法的流程

未完待续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源代码 hbase