hbase-region预分区(pre-splitting)

如果一个节点有过多的读写操作,会造成热点问题,HBase可能会因为Zookeeper的连接超时而关掉该节点,一个好的策略是将表预分割为固定数量的区域(region),并且这些区域均匀地分布在所有的服务器(regionserver)上,然后让HBase的自动分割功能来处理后面不断增加的数据。

RegionSplitter提供三个用于Pre-splitting的工具:HexStringSplit、UniformSplit、SplitAlgorithm。

HexStringSplit

row key是十六进制的字符串(hexadecimal ASCII)作为前缀的时候

HexHash(prefix)作为row key的前缀,其中Hexhash为最终得到十六进制字符串的hash算法
#方式一
create 'mytable', { NAME => 'info', COMPRESSION => 'snappy' },  {NUMREGIONS => 60, SPLITALGO => 'HexStringSplit'}

#方式二
hbase org.apache.hadoop.hbase.util.RegionSplitter mytable HexStringSplit -c 10 -f f1

UniformSplit

row key是字节数组arbitrary bytes的时候

某个hbase的表查询只是以随机查询为主,可以用UniformSplit的方式进行,按照原始byte值(从0x00~0xFF)右边以00填充。以这种方式分区的表在插入的时候需要对rowkey进行一个技巧性的改造, 比如原来的rowkey为rawStr,则需要对其取hashCode,然后进行按照比特位反转后放在最初rowkey串的前面
create 'tracker_total_live_active_fact', 'info',{NUMREGIONS => 15, SPLITALGO => 'UniformSplit'}

rowkey设计:

public static void main(String[] args) throws Exception {  
        Configuration conf = HBaseConfiguration.create();  
        conf.set("hbase.zookeeper.quorum", "hadoop1");  
        conf.set("hbase.zookeeper.property.clientPort", "2181");  
        HConnection connection = HConnectionManager.createConnection(conf);  
        HTableInterface table = connection.getTable("huanggang");  
        for (int i=1; i< 6553500; i++) {  
            byte[] rowKey = Bytes.add(Bytes.toBytes(Integer.reverse(Integer.valueOf(Integer.valueOf(i).hashCode()))), Bytes.toBytes(i));  
            System.out.println(rowKey);  
            Put put = new Put(rowKey);  
            put.add("f".getBytes(), "col1".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            put.add("f".getBytes(), "col2".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            put.add("f".getBytes(), "col3".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            put.add("f".getBytes(), "col4".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            put.add("f".getBytes(), "col5".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            put.add("f".getBytes(), "col6".getBytes(), Bytes.toBytes(new Random().nextInt(10000)));  
            table.put(put);  
        }  
        table.flushCommits();  
        table.close();  
    }  

SplitAlgorithm

SplitAlgorithm是一个接口,需要开发人员自己实现相应的分隔策略

SplitAlgorithm splitAlgo = new SplitAlgoInstance(conf, splitClass);//实例化自定义splitAlgorithm对象。

import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.RegionSplitter.SplitAlgorithm;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FileSplit implements SplitAlgorithm {


    //  public static final String SPLIT_KEY_FILE = "split-keys";

    private String splitKeyFile;

    public FileSplit(String splitKeyFile) {
        this.splitKeyFile = splitKeyFile;
    }

    @Override
    public byte[] split(byte[] start, byte[] end) {
        return null;
    }

    @Override
    public byte[][] split(int numberOfSplits) {
        BufferedReader reader = null;
        try {
            List<byte[]> regions = new ArrayList<byte[]>();
            //一行一行读
            reader = new BufferedReader(new FileReader(splitKeyFile));
            String line;
            while ((line = reader.readLine()) != null) {
//              System.out.println(line);
                if (line.trim().length() > 0) {
                    regions.add(Bytes.toBytes(line));
                }
            }
            return regions.toArray(new byte[0][]);
        } catch (IOException e) {
            throw new RuntimeException("Error reading splitting keys from " + splitKeyFile, e);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public byte[] firstRow() {
        return null;
    }

    @Override
    public byte[] lastRow() {
        return null;
    }

    @Override
    public void setFirstRow(String s) {

    }

    @Override
    public void setLastRow(String s) {

    }

    @Override
    public byte[] strToRow(String input) {
        return null;
    }

    @Override
    public String rowToStr(byte[] row) {
        return null;
    }

    @Override
    public String separator() {
        return null;
    }

    @Override
    public void setFirstRow(byte[] bytes) {

    }

    @Override
    public void setLastRow(byte[] bytes) {

    }
}

自定义分区

 create 'mytable', 'colfam1', {SPLITS => ['ROW-100','ROW-200','ROW-300','ROW-400']}

还可以指定分区文件

create 'mytable', { NAME => 'dim', COMPRESSION => 'snappy' }, { NAME => 'fact', COMPRESSION => 'snappy' },SPLITS_FILE => 'splits.txt'

分区文件

00|
01|
02|
03|
04|
05|
06|
07|
08|
09|
10|
11|
12|
13|
14|
15|
16|
17|
18|
19|
20|
21|
22|
23|
24|

这里是以一天的24小时作为前缀来设计rowkey的

参考站点:

http://blog.csdn.net/jdplus/article/details/47273983

http://blog.csdn.net/huanggang028/article/details/40819517

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿与禅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值