HBase优化之预分区
Posted HBase技术社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HBase优化之预分区相关的知识,希望对你有一定的参考价值。
如果在hbase shell中使用create建表时只写了表名和列族名,那么这张表将只有一个region ,当一个region的大小超过阈值时会自动split成两个,但split操作会带来资源消耗。region个数太少时,在数据量大、访问量大,或被批处理程序读写情况下性能可能会很差,并且伴随大批量读写而来的GC可能会使regionserver宕机,接着region被transit到其他节点上,将逐步拖垮HBase集群上的所有节点。
所以推荐在建表时进行预分区,充分考虑rowkey的分布做出合理的预分区方案,要考虑的点包括region的个数、region的大小等。
Region的个数
如果使用MapReduce读取HBase表数据,Map的个数等于该表region的个数,每个region都会有一个单独进程来处理,这个进程会逐条处理region中的每一行数据。举例来说如果只有一个region,那么读取数据的就只有一个进程;如果拆成10个数据均匀分布的region,那么10个map会带来10倍的效率提升。
大数据量情况下越发需要并行处理,因此我们往往希望源表的region的个数多一些。但是同时也要考虑集群的承载能力,HBase的region个数上限可以参考官网给出的如下公式,其中RS Xmx是regionserver的内存堆栈大小,官网建议每台20~24或更小,因为过大的内存会导致GC时间过长(GC方式从CMS改为G1后可以增大该值,机器内存足够的情况下可以翻倍甚至更大)。
((RS Xmx) *hbase.regionserver.global.memstore.size) / (hbase.hregion.memstore.flush.size *(# column families))。
即24G*0.45/128M=86.4个,在实际使用中很容易超过这个值。另外官网建议每个RS 20~200个regions是比较合理的。因此region个数也不是越多越好,还要考虑集群情况。我们可以在HBase WebUI上看到这个值。
对于不需要用MR批量读HBase表,相比需要MR读的表region个数可以少一些,以此来控制regionserver上region总数。
Region的大小
单个region最大大小官方推荐5~10GB,这是三备份前的数据大小,通过hbase.hregion.max.filesize配置,当超过这个值后region会split,估计好数据量并合理的划分region会减少不必要的性能损失。甚至设置足够大的值,日常监控中发现过大后手工做split。
预分区的方法
预建region可以在shell中或者程序中实现,网上很多文章,如下是一些例子,不再赘述。要想清楚rowkey的边界,比如对于全部都是数字开头的rowkey,分200个region,边界就是000,005,010……995。
hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt'
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
private void createTable() {
HBaseAdmin admin = null; String tableName="NewTable";
String columnFamilyName="cf";
try {
Configuration conf = HBaseConfiguration.create();
admin = new HBaseAdmin(conf);
TableName tableNameV = TableName.valueOf(tableName);
if (admin.tableExists(tableNameV)) {
System.out.println("Table " + tableName + " already
exist.");
return;
}
HTableDescriptor tableDesc = new
HTableDescriptor(tableNameV);
HColumnDescriptor columnDesc = new
HColumnDescriptor(columnFamilyName);
tableDesc.addFamily(columnDesc);
admin.createTable(tableDesc, splits());
System.out.println("Created table : " + tableName + "
successfully.");
} catch (Exception e) {
System.out.println("Failed create table " + tableName+ e.toString());
}
}
private static byte splits() {}
长按下面的二维码加入HBase技术社区微信群
以上是关于HBase优化之预分区的主要内容,如果未能解决你的问题,请参考以下文章