HBase数据库设计之RowKey

第1关:金融类RowKey设计

知识点

1.RowKey设计原则:唯一原则、排序原则、长度原则(越短越好)、散列原则

编程要求

根据提示,在右侧编辑器补充代码,完成以下需求:

  • 设计 RowKey

  • 完成查询某个卖家某段时间内的交易记录

package step1;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Task {


    /**
     * 生成 RowKey
     *
     * @param sellerId  卖家ID
     * @param timestamp 时间戳
     * @param orderId   订单ID
     * @return RowKey
     */
    public String createRowKey(String sellerId, String timestamp, String orderId) {
        /********** begin **********/
        String rowKey=sellerId+"-"+timestamp+"-"+orderId;
        return rowKey;
        /********** end **********/
    }


    /**
     * 查询某个卖家某段时间内的交易记录
     *
     * @param sellerId       卖家ID
     * @param startTimestamp 开始时间戳
     * @param endTimestamp   截止时间戳
     * @return map 存储 (rowkey,value)
     */
    public Map<String, String> findLogByTimestampRange(String sellerId, String startTimestamp, String endTimestamp) throws Exception {
        Map<String, String> map = new HashMap<>();
        /********** begin **********/
        Configuration conf=new Configuration();
        conf.set("hbase.zookeeper.quorum","127.0.0.1:2181");
        Connection connection=ConnectionFactory.createConnection(conf);
        Scan scan=new Scan();

        String startRow=sellerId+"-"+startTimestamp;
        String stopRow=sellerId+"-"+(endTimestamp+1);

        scan.withStartRow(startRow.getBytes());
        scan.withStopRow(stopRow.getBytes());
        Table table=connection.getTable(TableName.valueOf("deal"));
        ResultScanner scanner=table.getScanner(scan);
        for (Result result:scanner){
            String key = Bytes.toString(result.getRow());
            List<Cell> cells = result.listCells();
            for(Cell c:cells){
                String value = Bytes.toString(CellUtil.cloneValue(c));
                map.put(key, value);
            }
        }
  
        /********** end **********/
        return map;
    }


}

第2关:车联网RowKey设计

知识点

1.避免热点的方法

(1)预分区

(2)加盐:给 RowKey 分配一个随机前缀以使得它和之前的 RowKey 的开头不同

(3)哈希:使同一行永远用一个前缀加盐

(4)反转:反转固定长度或者数字格式的RowKey,使得RowKey中经常改变的部分放在前面

(5)时间戳反转

编程要求

根据提示,在右侧编辑器补充代码,完成以下需求:

  • 使用 hash 避免热点问题 --> 前缀:prefix = substr(md5(uid),0 ,5)
  • 查询某辆车在某个时间范围的交易记录
package step2;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Task {

    static String[] chars = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
	 * MD5 加密
     * @param str 需要加密的文本
     * @return 加密后的内容
     */
    public static String StringInMd5(String str) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("md5");
            byte[] result = md5.digest(str.getBytes());
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < result.length; i++) {
                byte x = result[i];
                int h = 0x0f & (x >>> 4);
                int l = 0x0f & x;
                sb.append(chars[h]).append(chars[l]);
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成 row
     *
     * @param carId     汽车ID
     * @param timestamp 时间戳
     * @return rowkey
     */
    public String createRowKey(String carId, String timestamp) {
        /********** begin **********/
        String prefix = StringInMd5(carId);
        String rowKey = prefix.substring(0, 5) + "-" + carId + "-" + timestamp;
        return rowKey;
        /********** end **********/
    }

    /**
     * 查询某辆车在某个时间范围的交易记录
     *
     * @param carId          车辆ID
     * @param startTimestamp 开始时间戳
     * @param endTimestamp   截止时间戳
     * @return map 存储 (rowkey,value)
     */
    public Map<String, String> findLogByTimestampRange(String carId, String startTimestamp, String endTimestamp) throws Exception {
        Map<String, String> map = new HashMap<>();
        /********** begin **********/
        Configuration conf = new Configuration();
        conf.set("hbase.zookeeper.quorum", "127.0.0.1:2181");
        Connection connection = ConnectionFactory.createConnection(conf);
        Scan scan = new Scan();
        String startRow = createRowKey(carId, startTimestamp);
        String stopRow = createRowKey(carId, endTimestamp + 1);
        scan.withStartRow(startRow.getBytes());
        scan.withStopRow(stopRow.getBytes());
        Table table = connection.getTable(TableName.valueOf("deal"));
        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            String key = Bytes.toString(result.getRow());
            List<Cell> cells = result.listCells();
            for (Cell c : cells) {
                String value = Bytes.toString(CellUtil.cloneValue(c));
                map.put(key, value);
            }
        }
        /********** end **********/
        return map;
    }


}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值