一、Region的切分
Region的自动切分
Region自动切分是HBase能够拥有良好扩张性的最重要因素之一,当然他也是分布式系统追求扩展性很好的功能。当一个Region大到一定程度,会进行分裂(split),HBase可以通过Region Split达到负载均衡。
自动切分的触发策略
自动切分的触发策略有很多种,在1.2.6版本中应该有六种触发策略。但是我们经常用的最多三种。
- ConstantSizeRegionSplitPolicy:0.94版本前默认切分策略
- I ncreasingToUpperBoundRegionSplitPolicy : 0.94版本~2.0版本默认切分策略
- SteppingSplitPolicy: 2.0版本默认切分策略
ConstantSizeRegionSplitPolicy
这种切分策略的原理是当region的一个store的大小大于设置的阈值之后才会触发切分。这里实际实现store的大小为压缩后的文件大小。
ConstantSizeRegionSplitPolicy切分策略的弊端,没有对于大表和小表做明显的区分。阈值(hbase。hergion.max.filesize)设置较大对大表比较友好,但是设置较小则对小表比较友好。如果说对小表比较友好,就会出现大表在整个集群产生大量的region,这对于集群管理和资源使用显然不是一件好事。
I ncreasingToUpperBoundRegionSplitPolicy
在前面ConstantSizeRegionSplitPolicy的切分策略中,达到固定的阈值就会触发切分,但是在I ncreasingToUpperBoundRegionSplitPolicy中并不是这样,它的阈值并不是固定的,会在一定条件下进行调整,调整规则和regionserver上的region个数有关系:count(regions)^3 * flush size * 2.当然阈值不会一只增大,范围由用户设置的MaxRegionFileSize来确定。
这样的设计很好的弥补了ConstantSizeRegionSplitPolicy大小表切分不便的现象。
SteppingSplitPolicy: 2.0版本默认切分策略
这种切分就基本与I ncreasingToUpperBoundRegionSplitPolicy的切分方式差不多,但是切分阈值的规则不一样,它的规则是flush size * 2,否则为MaxRegionFileSize。
Region切分流程
Hbase将整个切分过程包装成了一个事务,意图能够保证切分事务的原子性。整个切分分为三个阶段
prepare – execute – (rollback)
- prepare阶段:在内存中初始化两个子region,具体是生成两个HRegionInfo对象,包含tableName、regionName、startkey、endkey等。同时会生成一个transaction journal,这个对象用来记录切分的进展,具体见rollback阶段。
- execute阶段:切分的核心操作。见下图(来自 Hortonworks ):
- regionserver 更改ZK节点 /region-in-transition 中该region的状态为SPLITING。
- master通过watch节点/region-in-transition检测到region状态改变,并修改内存中region的状态,在master页面RIT模块就可以看到region执行split的状态信息。
- 在父存储目录下新建临时文件夹.split保存split后的daughter region信息。
- 关闭parent region:parent region关闭数据写入并触发flush操作,将写入region的数据全部持久化到磁盘。此后短时间内客户端落在父region上的请求都会抛出异常NotServingRegionException。
- 核心分裂步骤:在.split文件夹下新建两个子文件夹,称之为daughter A、daughter B,并在文件夹中生成reference文件,分别指向父region中对应文件。这个步骤是所有步骤中最核心的一个环节,生成reference文件日志如下所示
- 父region分裂为两个子region后, 将daughter A、daughter B拷贝到HBase根目录下,形成两个新的region。
- parent region通知修改 hbase.meta 表后下线,不再提供服务。下线后parent region在meta表中的信息并不会马上删除,而是标注split列、offline列为true,并记录两个子region。为什么不立马删除?且听下文分解。
- 开启daughter A、daughter B两个子region。通知修改 hbase.meta 表,正式对外提供服务。
- rollback阶段:如果execute阶段出现异常,则执行rollback操作。为了实现回滚,整个切分过程被分为很多子阶段,回滚程序会根据当前进展到哪个子阶段清理对应的垃圾数据。代码中使用 JournalEntryType 来表征各个子阶段。
二、Region预拆分
指定拆分算法
$ hbase org.apache.hadoop.hbase.util.RegionSplitter my_split_table HexStringSplit -c 10 -f mycf
其中:my_split_table:我们指定要新建的表名。
HexStringSplit:指定的拆分点算法为HexStringSplit。
-c:要拆分的Region数量。
-f:要建立的列族名称。
手动指定拆分点
#指定拆分点
create 'test_split2','mycf2',SPLITS=>['aaa','bbb','ccc','ddd','eee','fff']
#指定拆分文件
create 'students','baseinfo',SPLITS_FILE => '/home/hadoop/data/splits.txt'
三、Region的合并
合并的目的
如果删除了大量数据,很多Region变小,这时候分成多个Region就很浪费,可以把Region合并起来,Region的合并不是为了性能考虑,主要是出于维护的目的
合并分为两种
Minor一般由事件触发,Major一般由时间触发
相关控制
- Minor(1.2.0-cdh5.14.2版本)
- hbase.hregion.memstore.flush.size 缓存阈值大小
- hbase.hstore.compaction.max :每次compact的HFile的最大数目,默认是10
- hbase.hstore.compaction.kv.max:compact时批量读取和写入KeyValue数据的数量,默认是10
- Major Compaction
- hbase.hregion.majorcompaction 时间间隔
四、Flush和Compact操作
flush操作
flush 'tablename'
flush 'regionname'
compact操作
#compact一个表的所有regions
compact 't1'
#compact某个空闲的region
compact 'r1'
#compact一个region中的某个列族
compact 'r1', 'c1'
#compact一个表中的某个列族
compact 't1', 'c1'
六、Compaction - Control
Compaction总结
- 重写log文件并清除旧值
- 节约空间,提高读写速度
- 会占用大量系统空间和I/O,一般在系统空闲时进行
Flush -> Minor Compaction -> Major Compaction
- Flush:将memstore写到一个新的存储文件中
- Minor一般由事件触发,Major一般由时间触发
相关控制
- Flush: hbase.hregion.memstore.flush.size 文件大小
- Minor: hbase.hstore.compaction.min/max 文件数
- Major: hbase.hregion.majorcompaction 时间间隔