HBase Split 过程


 
看了下hbase split的代码 记录一下学习心得 
Java代码   收藏代码
  1. private void split(final HRegion parent, final byte [] midKey)  
  2. throws IOException {  
  3.     final long startTime = System.currentTimeMillis();  
  4.     SplitTransaction st = new SplitTransaction(parent, midKey);  
  5.     // If prepare does not return true, for some reason -- logged inside in  
  6.     // the prepare call -- we are not ready to split just now.  Just return.  
  7.     if (!st.prepare()) return;  
  8.     try {  
  9.       st.execute(this.server, this.server);  


SplitTransation表示处理split是一个类似事务性质的行为,接下来我们会经常和它打交道 
初始化了一个path:tablename/parent/split/ 

st.prepare():构造了两个HRegionInfo:hri_a和hri_b,a是top,其startkey为parent的startkey,endkey是midkey;hri_b是bottom,startkey为midkey,endkey是parent的endkey。 

然后st.execute(this.server, this.server); 

1.创建splitdir:tablename/parent/split/,在状态机中加入CREATE_SPLIT_DIR 
Java代码   收藏代码
  1. createSplitDir(this.parent.getFilesystem(), this.splitdir);  
  2.     this.journal.add(JournalEntry.CREATE_SPLIT_DIR);  

2.close parentregion,并返回所有的storefile,状态机加入CLOSED_PARENT_REGION 
  close的过程会刷一次磁盘memstore的数据写入磁盘; 
Java代码   收藏代码
  1. List<StoreFile> hstoreFilesToSplit;  
  2. hstoreFilesToSplit = this.parent.close(false);  


3.从rs的onlineregion列表中移除parent region,状态机添OFFLINED_PARENT 
Java代码   收藏代码
  1. services.removeFromOnlineRegions(this.parent.getRegionInfo().getEncodedName());  
  2. this.journal.add(JournalEntry.OFFLINED_PARENT);  


4.splitStoreFiles(this.splitdir, hstoreFilesToSplit); 
   多线程处理所有的storefiles.创建文件/table/parent/split/hri_a 
  (hri_b)/family/storefilename. parent,在该文件中写入boolean top和midkey
Java代码   收藏代码
  1. splitStoreFiles(this.splitdir, hstoreFilesToSplit);  
  2. this.journal.add(JournalEntry.STARTED_REGION_A_CREATION);  

    5.状态机添STARTED_REGION_A_CREATION,创建子Region A。将上面的hri_a下的文件move到table/hri_a下即变为/hbase/hri_a/family/storefilename.parent 

6.同理状态机添STARTED_REGION_B_CREATION而后创建子Region B 
Java代码   收藏代码
  1. this.journal.add(JournalEntry.STARTED_REGION_A_CREATION);  
  2. HRegion a = createDaughterRegion(this.hri_a,this.parent.flushRequester, this.parent.rsServices);  
  3. this.journal.add(JournalEntry.STARTED_REGION_B_CREATION);  
  4. HRegion b = createDaughterRegion(this.hri_b, this.parent.flushRequester, this.parent.rsServices);  


7.meta表中下线parent;将parent在meta表中offline和split标志置为true,parent 
  Region添加两列SPLITA和SPLITB,值为HRegioninfo 
8.状态机添PONR 
Java代码   收藏代码
  1. try{  
  2.      if (!testing) {  
  3.        MetaEditor.offlineParentInMeta(server.getCatalogTracker(),  
  4.            this.parent.getRegionInfo(), a.getRegionInfo(), b.getRegionInfo());  
  5.      }  
  6.    } catch(IOException e){  
  7.      throw e;  
  8.    } finally{  
  9.      this.journal.add(JournalEntry.PONR);  
  10.    }  


9.开两个线程open REGION A和B。 
  
  1>调用openRegion函数进行initilize,主要步骤如下 

   a)向hdfs上写入.regionInfo文件以便meta挂掉以便恢复 
   b)初始化其下的HStore,主要是LoadStoreFiles函数: 
       对于该store函数会构造storefile对象,从hdfs上获取路径和文件,每个文件一个 
      storefile对象,对每个storefile对象会读取文件上的内容创建一个 
       HalfStoreFileReader读对象来操作该region的父region上的相应的文件,及该 
       region上目前存储的是引用文件,其指向的是其父region上的相应的文件,对该 
       region的所有读或写都将关联到父region上 
  2>将子Region添加到rs的online region列表上,并添加到meta表上 
Java代码   收藏代码
  1. DaughterOpener aOpener = new DaughterOpener(server, services, a);  
  2.    DaughterOpener bOpener = new DaughterOpener(server, services, b);  
  3.    aOpener.start();  
  4.    bOpener.start();  
  5.    try {  
  6.      aOpener.join();  
  7.      bOpener.join();  
  8.    } catch (InterruptedException e) {  
  9.      Thread.currentThread().interrupt();  
  10.      throw new IOException("Interrupted " + e.getMessage());  
  11.    }  


整个过程如上所述,如果碰到异常的话,会进行rollback检查状态机上的状态并依次进行rollback

你可能感兴趣的:(hbase,split,region)