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));
		}
	}
}


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