hbase2.1.x 预分区和rowkey设计操作

上接:hbase2.1.x rowkey设计原则

提出需求

电信公司的通话详单,为了便于查询,将 用户的每一天的通话记录保存到一个 region 中

分析

见 hbase2.1.x rowkey设计原则 中的 热点问题

验证

建表

建表时指定 region 数量,并指定拆分算法

create 'call_log','info',{NUMREGIONS => 3, SPLITALGO => 'HexStringSplit'}

web查看

http://hadoop1:16010/table.jsp?name=call_log

  • 第一个region的rowkey范围:- 55555555
  • 第二个region的rowkey范围:55555555 - aaaaaaaa
  • 第三个region的rowkey范围:aaaaaaaa -

注意:长度是 8 个字符

代码

package top.malaoshi;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.MD5Hash;

import java.io.IOException;

public class TestRowKey {
    private Connection conn;

    /**
     * 创建hbase连接
     * @throws IOException
     */
    public void conn() throws IOException {
        //创建hbase配置对象
        Configuration conf= HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "hadoop1,hadoop2,hadoop3");// zookeeper地址
        conf.set("hbase.zookeeper.property.clientPort", "2181");// zookeeper端口
        //通过配置对象创建连接
        conn = ConnectionFactory.createConnection(conf);
    }

    public void testRowkey() throws IOException {
        //获取table对象
        Table table = conn.getTable(TableName.valueOf("call_log"));
        //主叫号码
        String tel="13900000001";

        for(int d=20211001;d<20211004;d++) {// 日期:20211001-20211004
            for (long i = 13800000001l; i < 13800000080l; i++) {//拨打的电话号
                String rowkey = tel +"_"+i + "_" +d+"_132530";//132530表示时间,这里为了演示,时间相同
                System.out.println(rowkey);
                //创建put对象
                Put put = new Put(Bytes.toBytes(rowkey));
                put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("李雷"));
                //执行put命令
                table.put(put);
            }
        }
        //关闭table
        table.close();
    }


    public void close() throws IOException {
        conn.close();
    }

    public static void main(String[] args) {
        TestRowKey trk=new TestRowKey();
        try {
            trk.conn();
            trk.testRowkey();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                trk.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

web页面查看

比较均匀分布在3台 region server

解决

使用 hbase2.1.x rowkey设计原则 中的 哈希(散列值)

rowkey 设计

rowkey 设计如下:

  1. 拼装成字符串:主叫号码_被叫号码_年月日_时分秒

  2. 将 主叫号码_被叫号码_年月日_时分秒 做 MD5 散列计算,并取出前 8 位。(由上面可知,rowkey的长度是 8 个字符)

  3. rowkey为:MD5前8位_主叫号码_被叫号码_年月日_时分秒

java代码

package top.malaoshi;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.MD5Hash;

import java.io.IOException;

public class TestRowKey {
    private Connection conn;

    /**
     * 创建hbase连接
     * @throws IOException
     */
    public void conn() throws IOException {
        //创建hbase配置对象
        Configuration conf= HBaseConfiguration.create();
        //通过配置对象创建连接
        conn = ConnectionFactory.createConnection(conf);
    }

    public void testRowkey2() throws IOException {
        //获取table对象
        Table table = conn.getTable(TableName.valueOf("call_log"));
        //主叫号码
        String tel="13900000001";

        for(int d=20211001;d<20211004;d++) {// 日期:20211001-20211004
            for (long i = 13800000001l; i < 13800000080l; i++) {//拨打的电话号
                String rowkey = tel +"_"+i + "_" +d+"_132530";//132530表示时间,这里为了演示,时间相同
                //根据rowkey生成md5
                String md5 = MD5Hash.getMD5AsHex(rowkey.getBytes());
                //md5值比较长,取出前8位
                String submd5 = md5.substring(0, 8);
                String newRowkey = submd5 + "_" + rowkey;
                System.out.println(newRowkey);
                //创建put对象
                Put put = new Put(Bytes.toBytes(newRowkey));
                put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("李雷"));
                //执行put命令
                table.put(put);
            }
        }
        //关闭table
        table.close();
    }


    public void close() throws IOException {
        conn.close();
    }

    public static void main(String[] args) {
        TestRowKey trk=new TestRowKey();
        try {
            trk.conn();
            trk.testRowkey();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                trk.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

web页面查看

比较均匀分布在3台 region server


原文出处:/show_1IX1yEik24c9.html