hbase region split源码分析
hbase region split : split执行调用流程: 1.HbaseAdmin发起split:### 2.RSRpcServices实现类执行split(Implements the regionserver RPC services.)### 3.CompactSplitThread类与SplitRequest类用来执行region切割:### 4.splitRequest执行doSplitting操作### 4.1初始化两个子region### 4.2执行切割#### 4.2.1:(创建子region。stepsBeforePONR函数)##### 4.2.2:子region执行:stepsAfterPONR函数执行(包含openDaughters函数):##### 4.2.3:HRegionServer添加子region到meta表,加入RegionServer##### 4.3等待region切分完成,修改meta表信息,报告master#### 1.HbaseAdmin发起split: public void split(final TableName tableName) throws IOException { split(tableName, null); } public void split(final ServerName sn, final HRegionInfo hri, byte[] splitPoint) throws IOException { if (hri.getStartKey() != null && splitPoint != null && Bytes.compareTo(hri.getStartKey(), splitPoint) == 0) { throw new IOException("should not give a splitkey which equals to startkey!"); } // TODO: There is no timeout on this controller. Set one! HBaseRpcController controller = rpcControllerFactory.newController(); controller.setPriority(hri.getTable()); // TODO: this does not do retries, it should. Set priority and timeout in controller AdminService.BlockingInterface admin = this.connection.getAdmin(sn); //hbase中split调用请求通过protobuf(AdminProtos)实现 ProtobufUtil.split(controller, admin, hri, splitPoint); 实现代码: try { admin.splitRegion(controller, request); } 2.RSRpcServices实现类执行split(Implements the regionserver RPC services.) 代码: try { checkOpen(); requestCount.increment(); Region region = getRegion(request.getRegion()); region.startRegionOperation(Operation.SPLIT_REGION); if (region.getRegionInfo().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) { throw new IOException("Can't split replicas directly. " + "Replicas are auto-split when their primary is split."); } LOG.info("Splitting " + region.getRegionInfo().getRegionNameAsString()); region.flush(true); byte[] splitPoint = null; if (request.hasSplitPoint()) { //确定切割点splitpoint splitPoint = request.getSplitPoint().toByteArray(); } ((HRegion)region).forceSplit(splitPoint); //请求region切割 regionServer.compactSplitThread.requestSplit(region, ((HRegion)region).checkSplit(), RpcServer.getRequestUser()); return SplitRegionResponse.newBuilder().build(); } 3.CompactSplitThread类与SplitRequest类用来执行region切割: 代码: try { this.splits.execute(new SplitRequest(r, midKey, this.server, user)); if (LOG.isDebugEnabled()) { LOG.debug("Split requested for " + r + ". " + this); } } try { //acquire a shared read lock on the table, so that table schema modifications //do not happen concurrently //获取table的读锁。。 tableLock = server.getTableLockManager().readLock(parent.getTableDesc().getTableName() , "SPLIT_REGION:" + parent.getRegionInfo().getRegionNameAsString()); try { tableLock.acquire(); } 4.splitRequest执行doSplitting操作 4.1### //初始化两个子region信息 this.hri_a = new HRegionInfo(hri.getTable(), startKey, this.splitrow, false, rid); this.hri_b = new HRegionInfo(hri.getTable(), this.splitrow, endKey, false, rid); 4.2### //执行切割 st.execute(this.server, this.server, user); 4.2.1:(创建子region。stepsBeforePONR函数)#### //创建两个子region PairOfSameType<Region> regions = createDaughters(server, services, user); 4.2.2:stepsAfterPONR函数执行(openDaughters):#### // 两个子region DaughterOpener线程 start DaughterOpener aOpener = new DaughterOpener(server, (HRegion)a); DaughterOpener bOpener = new DaughterOpener(server, (HRegion)b); //向hdfs上写入.regionInfo文件以便meta挂掉以便恢复 writeRegionInfoOnFilesystem(content, true); //初始化所有的hstore initializeStores(reporter, status); //LoadStoreFiles函数执行: if (files == null || files.size() == 0) { return new ArrayList<StoreFile>(); } // initialize the thread pool for opening store files in parallel.. ThreadPoolExecutor storeFileOpenerThreadPool = this.region.getStoreFileOpenAndCloseThreadPool("StoreFileOpenerThread-" + this.getColumnFamilyName()); CompletionService<StoreFile> completionService = new ExecutorCompletionService<StoreFile>(storeFileOpenerThreadPool); int totalValidStoreFile = 0; for (final StoreFileInfo storeFileInfo: files) { //HDFS上对应的路径和文件 completionService.submit(new Callable<StoreFile>() { @Override public StoreFile call() throws IOException { //每个文件创建一个StoreFile对象,对每个storefile对象会读取文件上的内容创建一个 HalfStoreFileReader读对象来操作该region的父region上的相应的文件,及该 region上目前存储的是引用文件,其指向的是其父region上的相应的文件,对该 region的所有读或写都将关联到父region上 StoreFile storeFile = createStoreFileAndReader(storeFileInfo); return storeFile; } }); totalValidStoreFile++; } //将子Region添加到rs的online region列表上,并添加到meta表上 { if (useZKForAssignment) { // add 2nd daughter first (see HBASE-4335) services.postOpenDeployTasks(b); } else if (!services.reportRegionStateTransition(TransitionCode.SPLIT, parent.getRegionInfo(), hri_a, hri_b)) { throw new IOException("Failed to report split region to master: " + parent.getRegionInfo().getShortNameToLog()); } // Should add it to OnlineRegions services.addToOnlineRegions(b); if (useZKForAssignment) { services.postOpenDeployTasks(a); } services.addToOnlineRegions(a); } 参考文章:http://blog.csdn.net/Pun_C/article/details/47173453