天天看点

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

继续阅读