hbase的预分区,以及rowkey的设计

未了防止habse的热点问题(单节点访问量太大或者插入到单台服务器节点),以及为了避免region的split的时候耗费时间,
可以提前进行预分区,但是预分区后rowkey是怎么落入到对应的分区呢?
这个问题到后面再解释;

private static Configuration conf = new Configuration();
public static void main(String[] args) throws IOException {
    String arg[] = new GenericOptionsParser(args).getRemainingArgs();
    if(arg.length<3) {
        System.out.println("参数不够!");
    }
    for(String a : arg) {
        System.out.println(a);
    }
    String tableName = "lzpTest";
    List<String> columnFamily = new ArrayList<>();
    conf.set("hbase.zookeeper.quorum","archive.cloudera.com,secondarynamenode2,datanode9");
    columnFamily.add("cf1");
    System.out.println("开始创建。。。。");
    createTableBySplitKeys(tableName,columnFamily);
}

进行创建预分区表,这里有两种方法来创建预分区,第一:getSplitKeysWithReginNum(int reginNum)方法reginNum是分区数,第二种:getSplitKeys()方法

    public static boolean createTableBySplitKeys(String tableName,List<String> columnFamily) {
    if(StringUtils.isBlank(tableName) || columnFamily ==null|| columnFamily.size()<0) {
        System.out.println("表名不存在!");
        return false;
    }
    try {
        System.out.println("正在创建。。。。");
        HBaseAdmin admin = new HBaseAdmin(conf);
        if(admin.tableExists(tableName)) {
            admin.disableTable(tableName.getBytes());
            admin.deleteTable(tableName.getBytes());
        }
        HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
        for(String family: columnFamily) {
            tableDescriptor.addFamily(new HColumnDescriptor(family));
        }
        byte[][] splitKeys = getSplitKeys();
        //创建表,指定splitkeys
        admin.createTable(tableDescriptor, splitKeys);
        System.out.println("预分区表创建成功!");
        
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

分区方法1,可以自己修改分区的规则,在keys数组,填写自己想要分区的规则;注意:为什么后面会跟着一个"|",是因为在ASCII码中,"|"的值是124,大于所有的数字和字母等符号,当然也可以用“~”(ASCII-126)。分隔文件的第一行为第一个region的stopkey,每行依次类推,最后一行不仅是倒数第二个region的stopkey,同时也是最后一个region的startkey。也就是说分区文件中填的都是key取值范围的分隔点,如下图所示:
988166-20170612112416118-304547192.png

    /**
 * 创建10个分区
 * @return
 */
private static byte[][] getSplitKeys() {
    String[] keys = new String[]{"10|","20|","30|","40|","50|","60|","70|","80|","90|"};
    byte[][] splitKeys = new byte[keys.length][];
    //必须使用treeset进行排序,否则在创建表时,会报错
    TreeSet<byte[]> rows = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);//升序排列
    for(int i =0;i<keys.length;i++) {
        rows.add(Bytes.toBytes(keys[i]));
    }
    
    Iterator<byte[]> rowKeyIter = rows.iterator();
    int i =0;
    while(rowKeyIter.hasNext()) {
        byte[] tempRow = rowKeyIter.next();
        rowKeyIter.remove();
        splitKeys[i] = tempRow;
        i++;
    }
    return splitKeys ;
}

分区方法2,可以根据需要,动态创建分区数

    /**
 * 动态创建分区数
 * @param reginNum
 * @return
 */
private static byte[][] getSplitKeysWithReginNum(int reginNum) {
    int total = 1000;//总步长
    int num = reginNum;//分区数
    
    //步长
    int step = total/num;
    //多余的步长
    int tail = total%num;
    //标准步长和非标准步长分界点
    //为了减少最后一个分区与其他分区的区间差别
    int split_step = num-tail-1;
    //总位数
    int length = Integer.toString(total-step).length();
    //标准化位数
    String format = "%0"+length+"d";
    //第一个分界点
    int limit = step;
    //准备预分区数组
    byte[][] splitKeys = new byte[num-1][];
    //遍历
    for(int i =0;i<num-1;i++) {
        if(i<split_step) {
            if(Integer.toString(limit).length()<length) {
                splitKeys[i] = String.format(format, limit).getBytes();
            }else {
                splitKeys[i] = Integer.toString(limit).getBytes();
            }
            limit += step;
        }else {
            if(Integer.toString(limit).length()<length) {
                splitKeys[i] = String.format(format, limit).getBytes();
            }else {
                splitKeys[i] = Integer.toString(limit).getBytes();
            }
            limit += (step+1);
        }
    }
    return splitKeys;
}

转载于:https://www.cnblogs.com/xihongxiaoshi/p/6992554.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值