HBase disable table的过程(转,删除表之前先disable table)
hbase的table delete之前需要将该table disable,今天结合源码分析一下disable的过程
首先看客户端HbaseAdmin.java中有接口
- publicvoiddisableTable(finalbyte[]tableName)
- publicvoiddisableTable(finalStringtableName)
它们的实现都是
- publicvoiddisableTableAsync(finalbyte[]tableName)throwsIOException{
- isMasterRunning();
- try{
- getMaster().disableTable(tableName);
- }catch(RemoteExceptione){
- throwe.unwrapRemoteException();
- }
- LOG.info("Starteddisableof"+Bytes.toString(tableName));
- }
这段代码的主要过程是通过rpc远程调用执行HMaster的disableTable();
所以我直接看HMaster的disableTable函数
- publicvoiddisableTable(finalbyte[]tableName)throwsIOException{
- this.executorService.submit(newDisableTableHandler(this,tableName,
- catalogTracker,assignmentManager));
- }
起了一个新线程DisableTableHadnler
首先判断meta表中是否存在该table,扫描meta表,若meta表不存在table则返回,抛出异常tablenotexist
该线程主要调用
- privatevoidhandleDisableTable()
将zk上面的/table/tablename标识为DISABLING
- this.assignmentManager.getZKTable().setDisablingTable(this.tableNameStr);
- booleandone=false;
- while(true){
- //Getlistofonlineregionsthatareofthistable.Regionsthatare
- //alreadyclosedwillnotbeincludedinthislist;i.e.thereturned
- //listisnotALLregionsinatable,itsallonlineregionsaccordingto
- //thein-memorystateonthismaster.
- finalList<HRegionInfo>regions=
- this.assignmentManager.getRegionsOfTable(tableName);
- if(regions.size()==0){
- done=true;
- break;
- }
- LOG.info("Offlining"+regions.size()+"regions.");
- BulkDisablerbd=newBulkDisabler(this.server,regions);
- try{
- if(bd.bulkAssign()){
- done=true;
- break;
- }
- }catch(InterruptedExceptione){
- LOG.warn("Disablewasinterrupted");
- //Preservetheinterrupt.
- Thread.currentThread().interrupt();
- break;
- }
- }
- //Flipthetabletodisabledifsuccess.
- if(done)this.assignmentManager.getZKTable().setDisabledTable(this.tableNameStr);
获取该table上的所有online的region集合。
对于这些regions bulkassign:起20个线程对所有region进行unassigned
- protectedvoidpopulatePool(ExecutorServicepool){
- for(HRegionInforegion:regions){
- if(assignmentManager.isRegionInTransition(region)!=null)continue;
- finalHRegionInfohri=region;
- pool.execute(newRunnable(){
- publicvoidrun(){
- assignmentManager.unassign(hri);
- }
- });
- }
- }
如上所示如果该Region已经在master的RIT队列中,则说明该region正在被处理,则忽略之
下面我们来看unassigned过程:
1. 该region必须online,在master的online队列中存在
2. 若该region在master的RIT队列中,且其state的状态是PENDING且force=true即表示即使该region正在closing ,force参数指定该region should be closed;
若在RIT中且不符合上面条件则忽略返回;
若不存在则将当前Region加入RIT队列中
3. serverManager.sendRegionClose(server, state.getRegion()),Master端与该Region所在RS进行通信,RPC调用HRegionServer的closeRegion(region)函数
HRegionServer端
closeRegion(region)
1. 该region在RS的online regions列表上
2. 起一个线程CloseRegionhandler实现以下步骤
1)setClosingState,在zk上创建unassigned下的该region节点将其值置为RS_ZK_REGION_CLOSING
2)region.close(abort),关闭region,主要是关闭region下每个Store的每个HFile的reader
3)将region从当前online列表中移除
4)在zk上将该节点置为RS_ZK_REGION_CLOSED
5)从RS的RIT队列中移除该region
Server端的主要逻辑即为如上所示
在上面过程中由于对zk上的unassigned节点进行了created和changed,且master端watch了该节点,当这些节点发生变化时会使得Master端也发生变化。
1)created时
- publicvoidnodeCreated(Stringpath){
- if(path.startsWith(watcher.assignmentZNode)){
- synchronized(regionsInTransition){
- try{
- RegionTransitionDatadata=ZKAssign.getData(watcher,path);
- if(data==null){
- return;
- }
- handleRegion(data);
- }catch(KeeperExceptione){
- master.abort("UnexpectedZKexceptionreadingunassignednodedata",e);
- }
- }
- }
- }
handleRegion的过程是将Master的RIT队列中该region的state置为CLOSING
2)变成Closed时
handleRegion将该region的state置为CLOSED然后力气一个线程CloseRegionHandler,此时如果zk上面/table下存在该table的节点,那么offlineDisabledRegion(HRegionInfo regionInfo)
1.删除zk上的unassigned节点,
2.clear regionplan
3.从Master的online region和server上移除该region
4.RIT中移除
整个过程结束。首先与hmaster进行通信,而后hmaster和rs进行通信,关闭region上各个HStore的Hfile的reader,在这个过程中涉及zk上节点的变化,master亦有相应的改变。