天天看點

HBase中region split的大緻流程

經過和社群讨論,并參照網上的一些文章,自己還看了一些源碼,終于将region split的大緻流程搞清楚了。

1. RegionServer開始split,首先會在ZK中建立一個名稱為“/hbase/region-in-transition/region-name”的znode,狀态為SPLITTING;

2. 由于Master在不停的觀察znode(/hbase/region-in-transition),是以它很快能感覺到新的變化;

3. RegionServer在HDFS上父region目錄下建立一個子目錄“.splits”;

4. RegionServer關閉父region,這會迫使一個memstore的flush,然後本地标記父region為offline狀态。此時,通路父region的用戶端将抛出NotServingRegionException。是以用戶端對此場景應當采用嘗試機制;

5. 在“.splits”目錄下,RegionServer為兩個子region分别建立目錄和必需的資料結構。然後,針對父region的每個storefile,為每個子region各建立一個reference檔案,即這些reference檔案将引用父region的storefile。在0.96.2的實作中,reference檔案的路徑為:父region目錄/.splits/子region_EncodedName/cf_name/storefile_name.父region_EncodedName;

6. RegionServer在真實的region目錄下(在0.96.2的實作中為/hbase/data/namespace_name/table_name/),為子region建立目錄,并将reference檔案移動到建立的目錄中;

7. RegionServer修改.META.表中父region的記錄,不但将其狀态置為offline,并且為其添加子region的資訊。并在.META.表中為每個子rigion添加一條記錄,并置記錄的server字段值為目前RegionServer的位址和端口。對.META.表的這些修改是原子性的;

8. RegionServer并行的打開子region,即子region将變為open狀态,并為用戶端提供讀寫服務;

9. RegionServer将ZK上的znode(/hbase/region-in-transition/region-name)狀态置為SPLIT,并等待master感覺後删除此zonode;

至此,split操作應該算是結束了。社群宣傳split操作很快,應該就是因為并沒有實際的拆分storefile,而是采用了非常小的reference檔案的原因。

split之後,子region通過reference檔案引用父region的資料。當子region發生compaction而生成自己的storefile後,reference檔案将會删除。master的GC任務将周期性的檢查父region是否仍被子region引用,如果沒有的話,将删除父region的所有資料,包括.META.表中的記錄和HDFS上的目錄結構(split過程中遺留的“.splits”也就順便被清理了。。。)

本文參考的源碼是0.96.2版本,不同版本的實作可能略有不同。

在此順便提及一下Hypertable的split過程,其實和Hbase類似。隻不過Hypertable在split後通常會馬上将一個新的子region/range移動到一個新的RegionServer/RangeServer上,并會伴随觸發major compaction。

本文還參考了以下兩篇文章:

http://zh.hortonworks.com/blog/apache-hbase-region-splitting-and-merging/#comment-501262

http://blog.csdn.net/u014393917/article/details/24119565

繼續閱讀