首页 > 数据库 > 数据库开发技术 > HBase的Region分裂与合并





Region分裂和Region合并都是HBase中非常重要的一环,是实现分布式可扩展性的基础,但是Region合并的使用场景较Region分裂更有限。
当HBase中空闲Region较多时,便会进行Region合并,以减少空闲Region的个数。同时,当HBase中的单个Region满足分裂策略时,便会进行分裂,其实,无论是Region分裂或者Region合并,都是基于提高HBase的性能出发的。下面开始学习吧。
以Region 分裂为主,Region简单了解吧。Region分裂流程如下:




HBase中常见的分裂触发策略有以下三种:ConstantSizeSplitPolicy,IncreasingToUpperBoundRegionSplitPolicy,SteppingSplitPolicy。
ConstantSizeSplitPolicy:HBase在0.94版本之前默认使用该分裂策略,当一个Region中最大Store的大小超过设置的阈值,该阈值通过hbase.hregion.max.filesize设置。便会触发分裂。
优点:在三种策略中最简单。
缺点:分裂策略对大表和小表没有明显的区分。如果阈值设置较大,对大表比较友好,但是小表不会触发分裂,如果设置较小,对于小表友好,但对大表会造成产生大量Region的问题。
IncreasingToUpperBoundRegionSplitPolicy:在0.94版本~2.0版本默认使用该分裂策略。该策略与ConstantSizeRegionSplitPolicy思路类似,一个Region中最大Store大小超过设置阈值就会触发分裂。与ConstantSizeRegionSplitPolicy不同的是,该策略中阈值是一个变化值,在一定条件下不断调整,阈值的值为(#regions)*(#regions)*(#regions)*flushsize*2,但是阈值不会无限增大,最大值为设置的MaxRegionFileSize。
优点:弥补了ConstantSizeRegionSplitPolicy的短板,能够自适应大表和小表,对集群规模较大的场景下对大表友好。
缺点:在大集群场景下,很多小表会产生大量小Region。
SteppingSplitPolicy:2.0版本默认使用该分裂策略。分裂阈值大小和待分裂Region所属表在当前RegionServer上的Region个数相关。如果Region个数等于1,分裂阈值为flushsize * 2,否则为MaxRegionFileSIze。
优点:对大集群中的大表,小表比IncreasingToUpperBoundRegionSplitPolicy更加友好,小表不会再产生大量的小Region。
除了这三种常见策略还有一些其他策略,一般使用默认方式即可,也可根据需要进行学习。


分裂点的定义:整个Region中最大Store中的最大文件中最中心的一个Block的首个rowkey,如果定位到的rowkey是整个文件的首个rowkey或者最后rowkey,则认为没有分裂点。
常见的没有分裂点的场景为:待分裂Region只有一个Block,执行split的时候会无法分裂。


Region分裂整体被分为一个事务,保证了分裂事务的原子性,总共分为三个阶段,prepare,execute和rollback。
prepare阶段:
HBase在内存中初始化两个子Region,会生成两个HRegionInfo对象,包含tableName,RegionName,startkey,endkey,还会生成一个transaction journal,记录分裂的进展。
execute阶段,该阶段可以详细分为以下几个步骤:
1).RegionServer与ZooKeeper交互,更改ZooKeeper节点下/region-in-transaction中Region的状态为SPLITING。
2).HMaster与ZooKeeper交互,通过检测ZooKeeper中/region-in-transaction下的Region状态,修改内存中Region的状态,在HMaster的Web UI页面可以看到Region执行Split的状态信息。
3).在父存储目录下建立临时文件夹.split,保存split后的daughter region信息。
4).关闭父Region,父Region关闭数据写入并触发flush操作,将写入Region的数据持久化到磁盘。此后一段时间客户端的请求会抛出异常NotServingRegionException。
5).在.split文件夹下新建两个子文件夹,称为daughter A与daughter B。在文件夹中生成reference文件,指向父Region中对应文件。reference文件名为父region对应的HFile文件.父Region。
6).父Region分裂为两个子Region后,将daguhter A与daughter B拷贝到HBase根目录下,形成两个新的Region。
7).父Region通知修改hbase:meta表后下线,不再提供服务,下线后父Region在meta表中的信息不会马上删除,而是将split和offline列标注为true。并记录两个子Region。
8).开启daughter A,daughter B两个子Region,修改hbase:meta表,正式对外提供服务。
rollback阶段:如果execute阶段出现异常,则会执行rollback操作。回滚过程中,会删除ZooKeeper中的拆分节点,清理父Region下的拆分目录,重新对父Region执行初始化操作并上线,然后清理子Region的存储目录,关闭子Region。
Region合并的典型场景:
假设在某些业务中某个接收写入的Region在长时间内不再接受任何写入,而且Region上的数据因为TTL过期被删除,此时Region没有任何存在的意义,即为空闲Region,当集群中空闲Region很多时,会导致集群管理维护成本增加,便可以通过在线合并功能将这些Region与相邻Region合并,以减少空闲Region数。
Region的合并流程如下:
1).客户端发送merge请求给HMaster。
2).HMaster将待合并的所有Region移动到同一个RegionServer上。
3).HMaster发送merger请求给RegionServer。
4).RegionServer启动一个本地事务执行merger操作。
5).merge操作将待合并的两个Region下线,并将两个Region的文件进行合并。
6).将这两个Region从hbase:meta中删除,并将新生成的Region添加到hbase:meta中。
7).将新生成的Region上线。
HBase使用merge_region命令执行Region合并,merge_region命令是一个异步操作,命令执行完后会立刻返回,需要手动检测合并是否成功,默认情况下,merger命令只能合并相邻的两个Region,非相邻的Region无法执行合并操作,但可以使用可选参数ture强制让不相邻的Region进行合并,但风险较大,一般生产上不建议。

reference文件是一个引用文件,但与Linux中的链接文件不同,他的文件内容不是用户数据,而是两部分构成:分裂点splitkey,boolean类型的变量。当为true时,表示该reference文件引用的是父文件的上半部分,当为false时,表示引用的是下半部分。

Region分裂过程不涉及数据的迁移,可以很快完成,分裂后子Region的文件实际没有任何用户数据,只存储元数据信息。reference根据文件名定位到真实数据所在文件路径。根据top字段和splitkey两个字段定位实际扫描范围。

父Region的数据会在子Region执行Major Compaction时迁移到子Region目录,在此过程中,子Region会将父目录中属于自己的所有数据读出来写入到自己的目录数据文件中。
HMaster会启动一个线程定期检查处于spliting状态的父Region,以此来确定父Region是否可以被清理,会先从meta表中读取删选split列为true的Region,然后加载分裂后的子Region,检查子Region是否还存在引用文件,如果不存在,即可删除。

这几天系统的对HBase中Region迁移,分裂,合并这一部分的知识点进行了学习,感觉对HBase的认知又清晰了一些。又是周一了,该去上班了,打工人,加油!

END




原文作者:DBA修行之路;如有侵权,请联系管理员删除。