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() {}


猜你喜欢

转载自blog.csdn.net/fantuanbaba/article/details/80810315
今日推荐