美文网首页hbase
hbase预分区误区

hbase预分区误区

作者: 仰望夜空一万次 | 来源:发表于2019-08-01 21:31 被阅读0次
预拆分表通常是一种比较好的实践。如果预先拆分表,则必须了解rowkey将如何分布在region边界上。是否所有的region都有rowkey能够访问。
举一个为什么这一点很重要的示例,考虑使用可显示十六进制字符作为键的前导位置的示例(例如,“0000000000000000”到“ffffffffffffffff”)。

创建预分区表的代码:

String startKeyString="0000000000000000";
String endKeyString="ffffffffffffffff";
int numRegions=10;
admin.createTable(tableDescriptor,startKeyString.getBytes(),endKeyString.getBytes(),numRegions);
//创建表,与下面的方法等价,生成一样region分布的表
int splitTimes=numRegions-3;//因为有两个空数组作为rowkey的开始和结束rowkey
byte[][] splitKeys=Bytes.split(startKeyString.getBytes(),endKeyString.getBytes(),splitTimes);
admin.createTable(tableDescriptor,splitKeys);

执行代码后,table的region分布如下:


image.png

当我们使用十六进制的字符作为rowkey前缀的时候,就会发生热点分区的问题。记录都会集中在如下四个region,因为十六进制字符rowkey的值区间为[0-9]和[a-f]。


image.png

做一些验证,向表中插入数据

byte[] rowKey=Bytes.toBytes("a");
 System.out.println(new String(rowKey)+"_"+rowKey.length);
 Put put = new Put(rowKey);
 put.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName), rowKey);
 table.put(put);

发现如下region接收到一次请求,即"a"与各个region的start key首字母与end key比较,"a"会落在"_"与"f"之间,所以此条记录会落在次rowkey区间的region上。


image.png

另外需要注意的一点,rowkey字符串的每个字节的ascii码会与startkey、endkey的每一个字节的ascii码比较。

/** 因为最后一个字符"e"的ascii码比"f"小,所以仍然落在split key "ffffffffffffffff"之前的region分区 */
byte[] rowKey=Bytes.toBytes("fffffffffffffffe");

/** 因为没有第三个字符与split key比较,所以"ff"小于"ffffffffffffffff" */
byte[] rowKey=Bytes.toBytes("ff");

上面两个rowkey的记录仍然会落在如下分区


image.png

错误分区代码总结:

  1. 预拆分表通常是一种最佳实践。但您需要让预拆分表满足rokwey可以访问任意的分区。虽然这个例子演示了十六进制键空间的问题,但任何键空间都可能发生同样的问题。需要了解你的数据,要知道rowkey的展示格式,知道各个region的start key与end key的展示格式。
  2. 错误的分区代码尽管不适合,但只要加以改进,将所有创建的region都可以在rowkey键空间中访问,那么使用十六进制键(更常见的目的是,可显示rowkey数据)仍然可以作为预拆分表的方案。

下面是如何为十六进制格式的rowkey进行预分区的正确示例:

public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) {
    byte[][] splits = new byte[numRegions-1][];
    //将16进制表示的字符串startKey转换为10进制的BigInteger类型
    BigInteger lowestKey = new BigInteger(startKey, 16);
    BigInteger highestKey = new BigInteger(endKey, 16);
    BigInteger range = highestKey.subtract(lowestKey);
    BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions));
    lowestKey = lowestKey.add(regionIncrement);
    for(int i=0; i < numRegions-1;i++) {
        BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i)));
        byte[] b = String.format("%016x", key).getBytes();
        splits[i] = b;
    }
    return splits;
}

 public void createTable3() throws IOException {
   String startKeyString="0000000000000000";
   String endKeyString="ffffffffffffffff";
   byte[][] splitKeys= getHexSplits(startKeyString,endKeyString,10);
   admin.createTable(tableDescriptor,splitKeys);
}

运行代码,创建好的region所有的startKey、endKey都为16进制的字符串表示。


image.png

ASCII表:


image.png

相关文章

  • hbase预分区误区

    创建预分区表的代码: 执行代码后,table的region分布如下: 当我们使用十六进制的字符作为rowkey前缀...

  • Hbase分区

    分区 HBase中,表会被划分为1…n个Region,被托管在RegionServer中。Region二个重要的属...

  • HBase框架基础(五)

    * HBase框架基础(五) 本节主要介绍HBase中关于分区的一些知识。 * HBase的RowKey设计 我们...

  • 原创-spark sql 写入hive较慢原因分析

    问题现象 hbase表30000条数据,使用spark读取hbase数据,按照某一字段值进行分区,分区数在1000...

  • Hbase预分区

    在上图中经常出现splits这个单词,它是什么意思呢?我们从表中数据开始分析。HBase的表的数据是存在Regio...

  • HBase(单机win10+WSL、集群独立安装)

    HBase的分区Region/RegionServer 设计与 Akka的分片 Region/ShardRegi...

  • Hbase 清空表,truncate与truncate_pres

    truncate会把表分区也清除掉 hbase(main)> truncate 'namespace:tableN...

  • 【HBase】HBase 自动拆分和预分区

    [TOC] 一、Region 自动拆分 HBase 中,表会被划分为1...n 个 Region,被托管在 Reg...

  • Hbase rowkey设计

    hbase的rowkey设计决定了数据的分区和查询的方式,是使用hbase前一定要想清楚的,以下简单列举了设计hb...

  • hbase:rowkey的设计

    hbase的rowkey设计决定了数据的分区和查询的方式,是使用hbase前一定要想清楚的,以下简单列举了设计hb...

网友评论

    本文标题:hbase预分区误区

    本文链接:https://www.haomeiwen.com/subject/sgkhdctx.html