hbase的region分区
HBase之五:hbase的region分區(qū)
一、Region 概念
Region是表獲取和分布的基本元素,由每個列族的一個Store組成。對象層級圖如下:
Table (HBase table)Region (Regions for the table)Store (Store per ColumnFamily for each Region for the table)MemStore (MemStore for each Store for each Region for the table)StoreFile (StoreFiles for each Store for each Region for the table)Block (Blocks within a StoreFile within a Store for each Region for the table)Region 大小
Region的大小是一個棘手的問題,需要考量如下幾個因素。
- Region是HBase中分布式存儲和負載均衡的最小單元。不同Region分布到不同RegionServer上,但并不是存儲的最小單元。
- Region由一個或者多個Store組成,每個store保存一個columns family,每個Strore又由一個memStore和0至多個StoreFile 組成。memStore存儲在內(nèi)存中, StoreFile存儲在HDFS上。
- HBase通過將region切分在許多機器上實現(xiàn)分布式。也就是說,你如果有16GB的數(shù)據(jù),只分了2個region, 你卻有20臺機器,有18臺就浪費了。
- region數(shù)目太多就會造成性能下降,現(xiàn)在比以前好多了。但是對于同樣大小的數(shù)據(jù),700個region比3000個要好。
- region數(shù)目太少就會妨礙可擴展性,降低并行能力。有的時候?qū)е聣毫Σ粔蚍稚ⅰ_@就是為什么,你向一個10節(jié)點的HBase集群導(dǎo)入200MB的數(shù)據(jù),大部分的節(jié)點是idle的。
- RegionServer中1個region和10個region索引需要的內(nèi)存量沒有太多的差別。
最好是使用默認的配置,可以把熱的表配小一點(或者受到split熱點的region把壓力分散到集群中)。如果你的cell的大小比較大(100KB或更大),就可以把region的大小調(diào)到1GB。region的最大大小在hbase配置文件中定義:
<property><name>hbase.hregion.max.filesize</name><value>10 * 1024 * 1024 * 1024</value></property>說明:
Region 拆分策略
Region的分割操作是不可見的,因為Master不會參與其中。RegionServer拆分region的步驟是,先將該region下線,然后拆分,將其子region加入到META元信息中,再將他們加入到原本的RegionServer中,最后匯報Master。
執(zhí)行split的線程是CompactSplitThread。
自定義拆分策略
可以通過設(shè)置RegionSplitPolicy的實現(xiàn)類來指定拆分策略,RegionSplitPolicy類的實現(xiàn)類有:
ConstantSizeRegionSplitPolicyIncreasingToUpperBoundRegionSplitPolicyDelimitedKeyPrefixRegionSplitPolicyKeyPrefixRegionSplitPolicy對于split,并不是設(shè)置了hbase.hregion.max.filesize(默認10G)為很大就保證不split了,需要有以下的算法:
- IncreasingToUpperBoundRegionSplitPolicy,0.94.0默認region split策略。根據(jù)公式min(r^2*flushSize,maxFileSize)確定split的maxFileSize,其中r為在線region個數(shù),maxFileSize由hbase.hregion.max.filesize指定。
- ConstantSizeRegionSplitPolicy,僅僅當region大小超過常量值(hbase.hregion.max.filesize大小)時,才進行拆分。
- DelimitedKeyPrefixRegionSplitPolicy,保證以分隔符前面的前綴為splitPoint,保證相同RowKey前綴的數(shù)據(jù)在一個Region中
- KeyPrefixRegionSplitPolicy,保證具有相同前綴的row在一個region中(要求設(shè)計中前綴具有同樣長度)。指定rowkey前綴位數(shù)劃分region,通過讀取table的prefix_split_key_policy.prefix_length屬性,該屬性為數(shù)字類型,表示前綴長度,在進行split時,按此長度對splitPoint進行截取。此種策略比較適合固定前綴的rowkey。當table中沒有設(shè)置該屬性,或其屬性不為Integer類型時,指定此策略效果等同與使用IncreasingToUpperBoundRegionSplitPolicy。
IncreasingToUpperBoundRegionSplitPolicy
這是0.94.0默認region split策略。根據(jù)根據(jù)公式min(r^2*flushSize,maxFileSize)確定split的maxFileSize,這里假設(shè)flushSize為128M:
第一次拆分大小為:min(10G,1*1*128M)=128M 第二次拆分大小為:min(10G,3*3*128M)=1152M 第三次拆分大小為:min(10G,5*5*128M)=3200M 第四次拆分大小為:min(10G,7*7*128M)=6272M 第五次拆分大小為:min(10G,9*9*128M)=10G 第五次拆分大小為:min(10G,11*11*128M)=10G可以看到,只有在第五次之后的拆分大小才為10G
配置拆分策略
你可以在hbase配置文件中定義全局的拆分策略,設(shè)置hbase.regionserver.region.split.policy的值即可,也可以在創(chuàng)建和修改表時候指定:
// 更新現(xiàn)有表的split策略 HBaseAdmin admin = new HBaseAdmin( conf); HTable hTable = new HTable( conf, "test" ); HTableDescriptor htd = hTable.getTableDescriptor(); HTableDescriptor newHtd = new HTableDescriptor(htd); newHtd.setValue(HTableDescriptor. SPLIT_POLICY, KeyPrefixRegionSplitPolicy.class.getName());// 指定策略 newHtd.setValue("prefix_split_key_policy.prefix_length", "2"); newHtd.setValue("MEMSTORE_FLUSHSIZE", "5242880"); // 5M admin.disableTable( "test"); admin.modifyTable(Bytes. toBytes("test"), newHtd); admin.enableTable( "test");說明:
二、hbase預(yù)分區(qū)示例
步驟:
1.規(guī)劃hbase預(yù)分區(qū)
首先就是要想明白數(shù)據(jù)的key是如何分布的,然后規(guī)劃一下要分成多少region,每個region的startkey和endkey是多少,然后將規(guī)劃的key寫到一個文件中。比如,key的前幾位字符串都是從0001~0010的數(shù)字,這樣可以分成10個region,劃分key的文件如下:
0001| 0002| 0003| 0004| 0005| 0006| 0007| 0008| 0009|為什么后面會跟著一個”|”,是因為在ASCII碼中,”|”的值是124,大于所有的數(shù)字和字母等符號,當然也可以用“~”(ASCII-126)。分隔文件的第一行為第一個region的stopkey,每行依次類推,最后一行不僅是倒數(shù)第二個region的stopkey,同時也是最后一個region的startkey。也就是說分區(qū)文件中填的都是key取值范圍的分隔點,如下圖所示:
2.hbase shell中建分區(qū)表,指定分區(qū)文件
在hbase shell中直接輸入create,會看到如下的提示:
Create a table with namespace=ns1 and table qualifier=t1 hbase> create 'ns1:t1', {NAME => 'f1', VERSIONS => 5} Create a table with namespace=default and table qualifier=t1 hbase> create 't1', {NAME => 'f1'}, {NAME => 'f2'}, {NAME => 'f3'} hbase> # The above in shorthand would be the following: hbase> create 't1', 'f1', 'f2', 'f3' hbase> create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true} hbase> create 't1', {NAME => 'f1', CONFIGURATION => {'hbase.hstore.blockingStoreFiles' => '10'}} Table configuration options can be put at the end. Examples: hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40'] hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40'] hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe' hbase> create 't1', {NAME => 'f1', VERSIONS => 5}, METADATA => { 'mykey' => 'myvalue' } hbase> # Optionally pre-split the table into NUMREGIONS, using hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname) hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'} hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit', CONFIGURATION => {'hbase.hregion.scan.loadColumnFamiliesOnDemand' => 'true'}} hbase> create 't1', {NAME => 'f1'}, {NAME => 'if1', LOCAL_INDEX=>'COMBINE_INDEX|INDEXED=f1:q1:8|rowKey:rowKey:10,UPDATE=true'}可以通過指定SPLITS_FILE的值指定分區(qū)文件,如果分區(qū)信息比較少,也可以直接用SPLITS分區(qū)。我們可以通過如下命令建一個分區(qū)表,指定第一步中生成的分區(qū)文件:
create 'split_table_test', 'cf', {SPLITS_FILE => 'region_split_info.txt'}假如我還想對hbase表做一個SNAPPY壓縮,應(yīng)該怎么寫呢?
這里注意,一定要將分區(qū)的參數(shù)指定單獨用一個大括號擴起來,因為分區(qū)是針對全表,而不是針對某一個column?family。
?
下面,我們登陸一下master的web頁面<Hmaster:60010>,查看一下hbase的表信息,找到剛剛新建的預(yù)分區(qū)表,進入查看region信息:
我們看到第一個region是沒有startkey的,最后一個region是沒有stopkey的。
?
三、hbase預(yù)分區(qū)方案
在HBase中,表會被劃分為1…n個Region,被托管在RegionServer中。Region二個重要的屬性:StartKey與EndKey表示這個Region維護的rowKey范圍,當我們要讀/寫數(shù)據(jù)時,如果rowKey落在某個start-end key范圍內(nèi),那么就會定位到目標region并且讀/寫到相關(guān)的數(shù)據(jù)。
1、由于業(yè)務(wù)數(shù)據(jù)一般都是從小到大增長的,根據(jù)上面hbase的region規(guī)則,就會出現(xiàn)“熱點寫”問題,隨著系統(tǒng)的運營,數(shù)據(jù)總是會往最大的start-key所在的region里寫,因為我們的rowkey總是會比之前的大,并且hbase的是按升序方式排序的。所以寫操作總是被定位到無上界的那個region中。
2、其次,由于寫熱點,我們總是往最大start-key的region寫記錄,之前分裂出來的region不會再被寫數(shù)據(jù),有點被打進冷宮的趕腳,它們都處于半滿狀態(tài),這樣的分布也是不利的。
如果在寫比較頻率的場景下,數(shù)據(jù)增長快,split的次數(shù)也會增多,由于split是比較耗時耗資源的,所以我們并不希望這種事情經(jīng)常發(fā)生。
看到這些缺點,我們知道,在集群的環(huán)境中,為了得到更好的并行性,我們希望有好的load blance,讓每個節(jié)點提供的請求處理都是均等的。我們也希望,region不要經(jīng)常split,因為split會使server有一段時間的停頓,如何能做到呢?
隨機散列與預(yù)分區(qū)
隨機散列與預(yù)分區(qū):二者結(jié)合起來,是比較完美的,預(yù)分區(qū)一開始就預(yù)建好了一部分region,這些region都維護著自已的start-end keys,再配合上隨機散列,寫數(shù)據(jù)能均等地命中這些預(yù)建的region,就能解決上面的那些缺點,大大地提高了性能。
提供2種思路: hash與partition.
假設(shè)rowKey原本是自增長的long型,可以將rowkey轉(zhuǎn)為hash再轉(zhuǎn)為bytes,加上本身id 轉(zhuǎn)為bytes,組成rowkey,這樣就生成隨便的rowkey。那么對于這種方式的rowkey設(shè)計,如何去進行預(yù)分區(qū)呢?
1.取樣,先隨機生成一定數(shù)量的rowkey,將取樣數(shù)據(jù)按升序排序放到一個集合里
2.根據(jù)預(yù)分區(qū)的region個數(shù),對整個集合平均分割,即是相關(guān)的splitKeys.
3.HBaseAdmin.createTable(HTableDescriptor tableDescriptor,byte[][] splitkeys)可以指定預(yù)分區(qū)的splitKey,即是指定region間的rowkey臨界值.
?
首先是熱點寫,我們總是會往最大的start-key所在的region寫東西,因為我們的rowkey總是會比之前的大,并且hbase的是按升序方式排序的。所以寫操作總是被定位到無上界的那個region中。
? ? 其次,由于寫熱點,我們總是往最大start-key的region寫記錄,之前分裂出來的region不會再被寫數(shù)據(jù),有點被打進冷宮的趕腳,它們都處于半滿狀態(tài),這樣的分布也是不利的。
? ? 如果在寫比較頻率的場景下,數(shù)據(jù)增長快,split的次數(shù)也會增多,由于split是比較耗時耗資源的,所以我們并不希望這種事情經(jīng)常發(fā)生。
? ? …………
? ? 看到這些缺點,我們知道,在集群的環(huán)境中,為了得到更好的并行性,我們希望有好的load blance,讓每個節(jié)點提供的請求處理都是均等的。我們也希望,region不要經(jīng)常split,因為split會使server有一段時間的停頓,如何能做到呢?
隨機散列與預(yù)分區(qū)。二者結(jié)合起來,是比較完美的,預(yù)分區(qū)一開始就預(yù)建好了一部分region,這些region都維護著自已的start-end keys,再配合上隨機散列,寫數(shù)據(jù)能均等地命中這些預(yù)建的region,就能解決上面的那些缺點,大大地提高了性能。
提供2種思路: hash 與 partition.?
一、hash思路
hash就是rowkey前面由一串隨機字符串組成,隨機字符串生成方式可以由SHA或者MD5等方式生成,只要region所管理的start-end keys范圍比較隨機,那么就可以解決寫熱點問題。
long currentId = 1L; byte [] rowkey = Bytes.add(MD5Hash.getMD5AsHex(Bytes.toBytes(currentId)).substring(0, 8).getBytes(),Bytes.toBytes(currentId));假設(shè)rowKey原本是自增長的long型,可以將rowkey轉(zhuǎn)為hash再轉(zhuǎn)為bytes,加上本身id 轉(zhuǎn)為bytes,組成rowkey,這樣就生成隨便的rowkey。那么對于這種方式的rowkey設(shè)計,如何去進行預(yù)分區(qū)呢?
? ? 1.取樣,先隨機生成一定數(shù)量的rowkey,將取樣數(shù)據(jù)按升序排序放到一個集合里
? ? 2.根據(jù)預(yù)分區(qū)的region個數(shù),對整個集合平均分割,即是相關(guān)的splitKeys.
? ? 3.HBaseAdmin.createTable(HTableDescriptor tableDescriptor,byte[][] splitkeys)可以指定預(yù)分區(qū)的splitKey,即是指定region間的rowkey臨界值.
如果知道Hbase數(shù)據(jù)表的key的分布情況,就可以在建表的時候?qū)base進行region的預(yù)分區(qū)。這樣做的好處是防止大數(shù)據(jù)量插入的熱點問題,提高數(shù)據(jù)插入的效率。
步驟:
1.創(chuàng)建split計算器,用于從抽樣數(shù)據(jù)中生成一個比較合適的splitKeys
public class HashChoreWoker implements SplitKeysCalculator{//隨機取機數(shù)目private int baseRecord;//rowkey生成器private RowKeyGenerator rkGen;//取樣時,由取樣數(shù)目及region數(shù)相除所得的數(shù)量.private int splitKeysBase;//splitkeys個數(shù)private int splitKeysNumber;//由抽樣計算出來的splitkeys結(jié)果private byte[][] splitKeys;public HashChoreWoker(int baseRecord, int prepareRegions) {this.baseRecord = baseRecord;//實例化rowkey生成器rkGen = new HashRowKeyGenerator();splitKeysNumber = prepareRegions - 1;splitKeysBase = baseRecord / prepareRegions;}public byte[][] calcSplitKeys() {splitKeys = new byte[splitKeysNumber][];//使用treeset保存抽樣數(shù)據(jù),已排序過TreeSet<byte[]> rows = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);for (int i = 0; i < baseRecord; i++) {rows.add(rkGen.nextId());}int pointer = 0;Iterator<byte[]> rowKeyIter = rows.iterator();int index = 0;while (rowKeyIter.hasNext()) {byte[] tempRow = rowKeyIter.next();rowKeyIter.remove();if ((pointer != 0) && (pointer % splitKeysBase == 0)) {if (index < splitKeysNumber) {splitKeys[index] = tempRow;index ++;}}pointer ++;}rows.clear();rows = null;return splitKeys;} } KeyGenerator及實現(xiàn) //interface public interface RowKeyGenerator {byte [] nextId(); } //implements public class HashRowKeyGenerator implements RowKeyGenerator {private long currentId = 1;private long currentTime = System.currentTimeMillis();private Random random = new Random();public byte[] nextId() {try {currentTime += random.nextInt(1000);byte[] lowT = Bytes.copy(Bytes.toBytes(currentTime), 4, 4);byte[] lowU = Bytes.copy(Bytes.toBytes(currentId), 4, 4);return Bytes.add(MD5Hash.getMD5AsHex(Bytes.add(lowU, lowT)).substring(0, 8).getBytes(),Bytes.toBytes(currentId));} finally {currentId++;}} }unit test case測試
@Test public void testHashAndCreateTable() throws Exception{HashChoreWoker worker = new HashChoreWoker(1000000,10);byte [][] splitKeys = worker.calcSplitKeys();HBaseAdmin admin = new HBaseAdmin(HBaseConfiguration.create());TableName tableName = TableName.valueOf("hash_split_table");if (admin.tableExists(tableName)) {try {admin.disableTable(tableName);} catch (Exception e) {}admin.deleteTable(tableName);}HTableDescriptor tableDesc = new HTableDescriptor(tableName);HColumnDescriptor columnDesc = new HColumnDescriptor(Bytes.toBytes("info"));columnDesc.setMaxVersions(1);tableDesc.addFamily(columnDesc);admin.createTable(tableDesc ,splitKeys);admin.close();}查看建表結(jié)果:執(zhí)行 scan ‘hbase:meta’
??以上我們只是顯示了部分region的信息,可以看到region的start-end key 還是比較隨機散列的。同樣可以查看hdfs的目錄結(jié)構(gòu),的確和預(yù)期的38個預(yù)分區(qū)一致:
??以上,就已經(jīng)按hash方式,預(yù)建好了分區(qū),以后在插入數(shù)據(jù)的時候,也要按照此rowkeyGenerator的方式生成rowkey,有興趣的話,也可以做些試驗,插入些數(shù)據(jù),看看數(shù)據(jù)的分布。
二、partition
? ? ?partition故名思義,就是分區(qū)式,這種分區(qū)有點類似于mapreduce中的partitioner,將區(qū)域用長整數(shù)(Long)作為分區(qū)號,每個region管理著相應(yīng)的區(qū)域數(shù)據(jù),在rowKey生成時,將id取模后,然后拼上id整體作為rowKey.這個比較簡單,不需要取樣,splitKeys也非常簡單,直接是分區(qū)號即可。直接上代碼吧:
public class PartitionRowKeyManager implements RowKeyGenerator,SplitKeysCalculator {public static final int DEFAULT_PARTITION_AMOUNT = 20;private long currentId = 1;private int partition = DEFAULT_PARTITION_AMOUNT;public void setPartition(int partition) {this.partition = partition;}public byte[] nextId() {try {long partitionId = currentId % partition;return Bytes.add(Bytes.toBytes(partitionId),Bytes.toBytes(currentId));} finally {currentId++;}}public byte[][] calcSplitKeys() {byte[][] splitKeys = new byte[partition - 1][];for(int i = 1; i < partition ; i ++) {splitKeys[i-1] = Bytes.toBytes((long)i);}return splitKeys;} }calcSplitKeys方法比較單純,splitKey就是partition的編號,我們看看測試類:
@Testpublic void testPartitionAndCreateTable() throws Exception{PartitionRowKeyManager rkManager = new PartitionRowKeyManager();//只預(yù)建10個分區(qū)rkManager.setPartition(10);byte [][] splitKeys = rkManager.calcSplitKeys();HBaseAdmin admin = new HBaseAdmin(HBaseConfiguration.create());TableName tableName = TableName.valueOf("partition_split_table");if (admin.tableExists(tableName)) {try {admin.disableTable(tableName);} catch (Exception e) {}admin.deleteTable(tableName);}HTableDescriptor tableDesc = new HTableDescriptor(tableName);HColumnDescriptor columnDesc = new HColumnDescriptor(Bytes.toBytes("info"));columnDesc.setMaxVersions(1);tableDesc.addFamily(columnDesc);admin.createTable(tableDesc ,splitKeys);admin.close();}同樣我們可以看看meta表和hdfs的目錄結(jié)果,其實和hash類似,region都會分好區(qū),在這里就不上圖了。
三、總結(jié) ? ??
通過partition實現(xiàn)的loadblance寫的話,當然生成rowkey方式也要結(jié)合當前的region數(shù)目取模而求得,大家同樣也可以做些實驗,看看數(shù)據(jù)插入后的分布。
在這里也順提一下,如果是順序的增長型原id,可以將id保存到一個數(shù)據(jù)庫,傳統(tǒng)的也好,redis的也好,每次取的時候,將數(shù)值設(shè)大1000左右,以后id可以在內(nèi)存內(nèi)增長,當內(nèi)存數(shù)量已經(jīng)超過1000的話,再去load下一個,有點類似于oracle中的sqeuence.
? ? ?隨機分布加預(yù)分區(qū)也不是一勞永逸的。因為數(shù)據(jù)是不斷地增長的,隨著時間不斷地推移,已經(jīng)分好的區(qū)域,或許已經(jīng)裝不住更多的數(shù)據(jù),當然就要進一步進行split了,同樣也會出現(xiàn)性能損耗問題,所以我們還是要規(guī)劃好數(shù)據(jù)增長速率,觀察好數(shù)據(jù)定期維護,按需分析是否要進一步分行手工將分區(qū)再分好,也或者是更嚴重的是新建表,做好更大的預(yù)分區(qū)然后進行數(shù)據(jù)遷移。小吳只是菜鳥,運維方面也只是自已這樣認為而已,供大家作簡單的參考吧。如果數(shù)據(jù)裝不住了,對于partition方式預(yù)分區(qū)的話,如果讓它自然分裂的話,情況分嚴重一點。因為分裂出來的分區(qū)號會是一樣的,所以計算到partitionId的話,其實還是回到了順序?qū)懩甏?#xff0c;會有部分熱點寫問題出現(xiàn),如果使用partition方式生成主鍵的話,數(shù)據(jù)增長后就要不斷地調(diào)整分區(qū)了,比如增多預(yù)分區(qū),或者加入子分區(qū)號的處理.(我們的分區(qū)號為long型,可以將它作為多級partition)
? ??
? ? ?OK,寫到這里,基本已經(jīng)講完了防止熱點寫使用的方法和防止頻繁split而采取的預(yù)分區(qū)。但rowkey設(shè)計,遠遠也不止這些,比如rowkey長度,然后它的長度最大可以為char的MAXVALUE,但是看過之前我寫KeyValue的分析知道,我們的數(shù)據(jù)都是以KeyValue方式存儲在MemStore或者HFile中的,每個KeyValue都會存儲rowKey的信息,如果rowkey太大的話,比如是128個字節(jié),一行10個字段的表,100萬行記錄,光rowkey就占了1.2G+所以長度還是不要過長,另外設(shè)計,還是按需求來吧。
? ? ?最后題外話是我想分享我在github中建了一個project,希望做一些hbase一些工具:https://github.com/bdifn/hbase-tools,如果本地裝了git的話,可以執(zhí)行命令: git clone https://github.com/bdifn/hbase-tools.git目前加了一個region-helper子項目,也是目前唯一的一個子項目,項目使用maven管理,主要目的是幫助我們設(shè)計rowkey做一些參考,比如我們設(shè)計的隨機寫和預(yù)分區(qū)測試,提供了抽樣的功能,提供了檢測隨機寫的功能,然后統(tǒng)計按目前rowkey設(shè)計,隨機寫n條記錄后,統(tǒng)計每個region的記錄數(shù),然后顯示比例等。
? ? ?測試仿真模塊我程為simualtor,主要是模擬hbase的region行為,simple的實現(xiàn),僅僅是上面提到的預(yù)測我們rowkey設(shè)計后,建好預(yù)分區(qū)后,寫數(shù)據(jù)的的分布比例,而emulation是比較逼真的仿真,設(shè)想是我們寫數(shù)據(jù)時,會統(tǒng)計數(shù)目的大小,根據(jù)我們的hbase-site.xml設(shè)定,模擬memStore行為,模擬hfile的行為,最終會生成一份表的報表,比如分區(qū)的數(shù)據(jù)大小,是否split了,等等,以供我們?nèi)ピO(shè)計hbase表時有一個參考,但是遺憾的是,由于時間關(guān)系,我只花了一點業(yè)余時間簡單搭了一下框架,目前沒有更一步的實現(xiàn),以后有時間再加以完善,當然也歡迎大家一起加入,一起學(xué)習(xí)吧。
? ? ?
? ? ?項目使用maven管理,為了方便測試,一些組件的實例化,我使用了java的SPI,download源碼后,如果想測試自已的rowKeyGeneator的話,打開com.bdifn.hbasetools.regionhelper.rowkey.RowKeyGenerator文件后,替換到你們的ID生成器就可以了。如果是hash的話,抽樣和測試等,都是可以復(fù)用的。
? ? 如測試代碼:
public class HBaseSimulatorTest {//通過SPI方式獲取HBaseSimulator實例,SPI的實現(xiàn)為simgpleprivate HBaseSimulator hbase = BeanFactory.getInstance().getBeanInstance(HBaseSimulator.class);//獲取RowKeyGenerator實例,SPI的實現(xiàn)為hashRowkeyprivate RowKeyGenerator rkGen = BeanFactory.getInstance().getBeanInstance(RowKeyGenerator.class);//初如化苦工,去檢測100w個抽樣rowkey,然后生成一組splitKeysHashChoreWoker worker = new HashChoreWoker(1000000,10);@Testpublic void testHash(){byte [][] splitKeys = worker.calcSplitKeys();hbase.createTable("user", splitKeys);//插入1億條記錄,看數(shù)據(jù)分布TableName tableName = TableName.valueOf("user");for(int i = 0; i < 100000000; i ++) {Put put = new Put(rkGen.nextId());hbase.put(tableName, put);}hbase.report(tableName);}@Testpublic void testPartition(){//default 20 partitions.PartitionRowKeyManager rkManager = new PartitionRowKeyManager();byte [][] splitKeys = rkManager.calcSplitKeys();hbase.createTable("person", splitKeys);TableName tableName = TableName.valueOf("person");//插入1億條記錄,看數(shù)據(jù)分布for(int i = 0; i < 100000000; i ++) {Put put = new Put(rkManager.nextId());hbase.put(tableName, put);}hbase.report(tableName);} }? ? 執(zhí)行結(jié)果:
? ??
Execution Reprort:[StartRowkey:puts requsts:(put ratio)] :9973569:(1.0015434) 1986344a\x00\x00\x00\x00\x00\x01\x0E\xAE:9999295:(1.0041268) 331ee65f\x00\x00\x00\x00\x00\x0F)g:10012532:(1.005456) 4cbfd4f6\x00\x00\x00\x00\x00\x00o0:9975842:(1.0017716) 664c6388\x00\x00\x00\x00\x00\x02\x1Du:10053337:(1.0095537) 800945e0\x00\x00\x00\x00\x00\x01\xADV:9998719:(1.0040689) 99a158d9\x00\x00\x00\x00\x00\x0BZ\xF3:10000563:(1.0042541) b33a2223\x00\x00\x00\x00\x00\x07\xC6\xE6:9964921:(1.000675) ccbcf370\x00\x00\x00\x00\x00\x00*\xE2:9958200:(1.0) e63b8334\x00\x00\x00\x00\x00\x03g\xC1:10063022:(1.0105262) total requests:100000000 Execution Reprort:[StartRowkey:puts requsts:(put ratio)] :5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x01:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x02:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x03:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x04:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x05:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x06:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x07:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x08:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x09:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0A:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0B:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0C:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0D:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0E:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x0F:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x10:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x11:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x12:5000000:(1.0) \x00\x00\x00\x00\x00\x00\x00\x13:5000000:(1.0) total requests:100000000?
?
?
?
?
分類: hadoop-hbase 標簽: Hbase, hadoop-hbase 好文要頂 關(guān)注我 收藏該文 duanxz關(guān)注 - 18
粉絲 - 248 +加關(guān)注 0 0 ? 上一篇:HBase之二:Hbase優(yōu)化
? 下一篇:Maven構(gòu)建項目速度太慢的解決辦法 Maven 調(diào)試
<div class="postDesc">posted on <span id="post-date">2013-06-25 13:10</span> <a href="http://www.cnblogs.com/duanxz/">duanxz</a> 閱讀(<span id="post_view_count">2342</span>) 評論(<span id="post_comment_count">0</span>) <a href="https://i.cnblogs.com/EditPosts.aspx?postid=3154487" rel="nofollow">編輯</a> <a href="#" onclick="AddToWz(3154487);return false;">收藏</a></div>
總結(jié)
以上是生活随笔為你收集整理的hbase的region分区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络聊天室Java群聊私聊_Java S
- 下一篇: Andorid性能优化之tracevie