hbase的预分区

HBase中,表会被划分为1...n个Region,被托管在RegionServer中。Region二个重要的属性:StartKey与 EndKey表示这个Region维护的rowKey范围,当我们要读/写数据时,如果rowKey落在某个start-endkey范围内,那么就会定位到目标region并且读/写到相关的数据

当我们只是通过HBaseAdmin指定TableDescriptor来创建一张表时,只有一个region,正处于混沌时期,start-end key无边界,可谓海纳百川。啥样的rowKey都可以接受,都往这个region里装,然而,当数据越来越多,region的size越来越大时,大到 一定的阀值,hbase认为再往这个region里塞数据已经不合适了,就会找到一个midKey将region一分为二,成为2个region,这个过 程称为分裂

如果我们就这样默认地,建表,表里不断地Put数据,更严重的是我们的rowkey还是顺序增大的,是比较可怕的。存在的缺点比较明显。

如果我们所设计的rowkey是单调递增的,这样的rowkey很有可能会全部包含在一个region的范围内,这样的话就会导致只有管理这个region的regionserver工作,而其他的regionserver处于闲置状态,也就是负载不均衡。因此,rowkey的设计和预分区是很有必要的。

我们将随机散列和预分区结合起来,预分区一旦创建好,就会管理自己的startkey和endkey,再配合随机散列对rowkey设计,就能够解决上面这些缺点,从而提高性能。

实现预分区的步骤:

1.取样,根据rowkey的生成策略随机的生成一定数量的rowkey,将取样的结果放进集合当中

2.根据预测表中将会存储的数据大小,设置region的个数。

3.根据region的个数对取样数据进行均匀的分割,比如我们设置的region数量为5,取样的数据个数为1000,那么我们只需要4个临界的rowkey就可以将这些数据分割为5个region,就是这个道理。

按照上述的分区步骤,我们分割出来的分区第一个region是没有上限的,最后一个是没有下限的,剩下的region都维护着自己的startkey和endkey,这样我们就完成了对于表的预分区。

下面是具体的代码实现:

package com.wangl.hadoop.hbase.prepartition;

import java.util.Iterator;
import java.util.TreeSet;

import org.apache.hadoop.hbase.util.Bytes;

public class HashChorWorker {
	//随机采样数目
	private int baseRecord;
	//rowkey生成工具
	private RowKeyGenerator rkGen;
	//取样时,由取样数目及region数相除得到的数
	private int splitKeyBase;
	//splitKeys个数
	private int splitKeysNumber;
	//抽样的计算结果
	private byte[][] splitKeys;
	
	public HashChorWorker(int baseRecord, int prepareRegions){
		this.baseRecord = baseRecord;
		this.splitKeyBase = baseRecord/prepareRegions;
		this.rkGen = new RowKeyGenerator();
		//需要的split key的个数,如分成10个区,只需要9个分隔符
		this.splitKeysNumber = prepareRegions - 1;
	}
	
	public byte[][] calSplitKeys(){
		splitKeys = new byte[splitKeysNumber][];
		//使用treeset保存抽样数据,并排序(定义时指定排序策略)
		TreeSet rows = new TreeSet(Bytes.BYTES_RAWCOMPARATOR);
		for(int i=0;i rowKeyit = rows.iterator();
		int index = 0;
		//因为取样数据是排过序的,所以按照被分割的数量每个splitKeysNumber个从抽样数据中取出一个作为region的分割key
		while(rowKeyit.hasNext()){
			byte[] tempRow = rowKeyit.next();
			rowKeyit.remove();
			if(pointer!=0 && pointer%splitKeyBase == 0){
				if(index < splitKeysNumber){
					splitKeys[index] = tempRow;
					index ++;
				}
			}
			pointer ++;
		}
		rows.clear();
		rows = null;
		return splitKeys;
	}
	
	public static void main(String args[]){
		HashChorWorker h = new HashChorWorker(100, 3);
		byte[][] skeys = h.calSplitKeys();
		for(byte[] k : skeys){
			System.out.println(Bytes.toString(k));
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章