1、概述
每一个region维护着startRow与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护。(默认一个分区,范围是(-∞,+∞))
2、预分区操作
2.1、手动指定(开发中不使用)
//1、设置分区键
//四个分区键
create 'staff1','info','partition1',SPILTS => ['1000','2000','3000','4000']
//16进制序列预分区
create ‘staff2’,'info','partition2',{NUMREGIONS => 15,SPILTALGO => 'HexStringSplit'}
//2、按照文件设置规则分区
//hbase 根目录创建分区键文件
//spilt.txt 1000 2000 3000 4000
create 'staff3','partition3',SPLITS_FILE => 'splits.txt'
2.2、使用JavaAPI创建预分区(开发中使用)
创建表的时候创建预分区
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class HBaseUtils {
private static ThreadLocal<Connection> connHolder = new ThreadLocal<Connection>();
private static Connection connection = null;
private HBaseUtils() {
}
/**
* 获取hbase连接对象
*/
public static Connection getHbaseConnection() throws IOException {
Connection conn = connHolder.get();
if(conn ==null){
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "192.168.1.102");
conf.set("hbase.zookeeper.property.clientPort", "2181");
conn = ConnectionFactory.createConnection(conf);
connHolder.set(conn);
}
return conn;
}
/**
* 关闭连接
*/
public static void close() throws IOException {
Connection conn = connHolder.get();
if(conn!=null){
conn.close();
connHolder.remove();
}
}
/**
* 生成分区键
*/
public static byte[][] getRegionKeys(int regionCount){
byte[][] bs = new byte[regionCount-1][];
/*
此处的分区键使用了‘0|’、‘1|’,‘2|’,‘3|’的形式,使得0开头的rowkey可以进入该分区
因为Hbase中的rowkey是按照ANSCⅡ排序的,‘|’是ANSCⅡ中第二大的字符,第一大的是‘}’(其用来分割)
这样可以使得rowkey以0开头,后面的字符都比‘|’小,可以进入该分区
eg:0qqq --> 'q'<'|' 进入该分区
*/
for (int i = 0; i < regionCount - 1; i++) {
bs[i] = Bytes.toBytes(i + "|");
}
return bs;
}
/**
* 创建预分区表
*/
public static void createTablePrePartition(String tableName,int regionCount, String... columnFamily) throws
MasterNotRunningException, ZooKeeperConnectionException, IOException {
Connection conn = connHolder.get();
Admin admin = conn.getAdmin();
//判断表是否存在
if (isTableExist(tableName)) {
System.out.println("表" + tableName + "已存在");
//System.exit(0);
} else {
//创建表属性对象,表名需要转字节
HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf(tableName));
//创建多个列族
for (String cf : columnFamily) {
descriptor.addFamily(new HColumnDescriptor(cf));
}
//根据对表的配置,创建预分区表
admin.createTable(descriptor,getRegionKeys(regionCount));
System.out.println("表" + tableName + "创建成功!");
}
}
}
获取分区号(👆中的一个函数)
/**
*生成分区号
*/
public static int getRegionNum(String rowkey,int regionCount){
int regionNum;
int hash = rowkey.hashCode();
//一个自然数n & (n-1) = 0,其为2的x次方
if(regionCount > 0 && (regionCount & (regionCount - 1)) == 0){
//2^N
regionNum = hash & (regionCount - 1);
}else{
regionNum = hash % (regionCount);
}
return regionNum;
}