表的设计

  • 列蔟:推荐1-2个,能使用1个就不是使用2个
  • 版本的设计:如果我们的项目不需要保存历史的版本,直接按照默认配置VERSIONS=1就OK。如果项目中需要保存历史的变更信息,就可以将VERSIONS设置为>1。但是设置为大于1也就意味着要占用更多的空间
  • 数据的压缩:在创建表的时候,可以针对列蔟指定数据压缩方式(GZ、SNAPPY、LZO)。GZ方式是压缩比最高的,13%左右的空间,但是它的压缩和解压缩速度慢一些

避免热点的关键操作

  1. 预分区

    • 在创建表的时候,配置一些策略,让一个table有多个region,分布在不同的HRegionServer中
    • HBase会自动进行split,如果一个region过大,HBase会自动split成两个,就是根据rowkey来横向切分
  2. rowkey设计

    • 反转:举例:手机号码、时间戳,可以将手机号码反转

    • 加盐:在rowkey前面加随机数,加了随机数之后,就会导致数据查询不出来,因为HBase默认是没有二级索引的

    • hash:根据rowkey中的某个部分取hash,因为hash每次计算都一样的值。所以,我们可以用hash操作获取数据

    • 这几种策略,因为要将数据均匀分布在集群中的每个RegionServer,所以其核心就是把rowkey打散后放入到集群节点中,所以数据不再是有序的存储,会导致scan的效率下降

预分区

  • 预分区有两种策略

    • startKey、endKey来预分区 [10, 40, 50]

  • 直接指定数量,startKey、endKey由hbase自动生成,还需要指定key的算法

  • HBase的数据都是存放在HDFS中

    • /hbase/data/命名空间/表/列蔟/StoreFiles

建表指令

# 一、命名空间
# 1. 创建一个命名空间
create_namespace 'MOMO_CHAT'# 2. 查看命名空间
list_namespace# 3. 删除之前的命名空间
drop_namespace 'MOMO_CHAT'# 4. 查看某个具体的命名空间
describe_namespace 'MOMO_CHAT'
describe_namespace 'default'# 5. 在命令MOMO_CHAT命名空间下创建名为:MSG的表,该表包含一个名为C1的列蔟。
# 注意:带有命名空间的表,使用冒号将命名空间和表名连接到一起
create "MOMO_CHAT:MSG", "C1"# 6. 指定修改某个表的列蔟,它的压缩方式
alter "MOMO_CHAT:MSG", {NAME => "C1", COMPRESSION => "GZ"}# 7. 删除之前创建的表
disable "MOMO_CHAT:MSG"
drop "MOMO_CHAT:MSG"# 8. 在创建表时需要指定预分区
create 'MOMO_CHAT:MSG', {NAME => "C1", COMPRESSION => "GZ"}, { NUMREGIONS => 6, SPLITALGO => 'HexStringSplit'}

可以看到已经有了六个region。

随机生成一条消息

  1. 通过ExcelReader工具类从Excel文件中读取数据,放入到一个Map结构中

    • key:字段名
    • value:List,字段对应的数据列表
  2. 创建getOneMessage方法,这个方法专门用来根据Excel读取到的数据,随机生成一个Msg实体对象
    • 调用ExcelReader.randomColumn方法来随机获取一个列的数据
  3. 注意:消息使用的是系统当前时间,时间的格式是:年-月-日 小时:分钟:秒
public class MoMoMsgGen {public static void main(String[] args) {// 读取Excel文件中的数据Map<String, List<String>> resultMap =ExcelReader.readXlsx("D:\\课程研发\\51.V8.0_NoSQL_MQ\\2.HBase\\3.代码\\momo_chat_app\\data\\测试数据集.xlsx", "陌陌数据");System.out.println(getOneMessage(resultMap));}/*** 基于从Excel表格中读取的数据随机生成一个Msg对象* @param resultMap Excel读取的数据(Map结构)* @return 一个Msg对象*/public static Msg getOneMessage(Map<String, List<String>> resultMap) {// 1.   构建Msg实体类对象Msg msg = new Msg();// 将当前系统的时间设置为消息的时间,以年月日 时分秒的形式存储SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 获取系统时间Date now = new Date();msg.setMsg_time(simpleDateFormat.format(now));// 2.   调用ExcelReader中的randomColumn随机生成一个列的数据// 初始化sender_nickyname字段,调用randomColumn随机取nick_name设置数据msg.setSender_nickyname(ExcelReader.randomColumn(resultMap, "sender_nickyname"));msg.setSender_account(ExcelReader.randomColumn(resultMap, "sender_account"));msg.setSender_sex(ExcelReader.randomColumn(resultMap, "sender_sex"));msg.setSender_ip(ExcelReader.randomColumn(resultMap, "sender_ip"));msg.setSender_os(ExcelReader.randomColumn(resultMap, "sender_os"));msg.setSender_phone_type(ExcelReader.randomColumn(resultMap, "sender_phone_type"));msg.setSender_network(ExcelReader.randomColumn(resultMap, "sender_network"));msg.setSender_gps(ExcelReader.randomColumn(resultMap, "sender_gps"));msg.setReceiver_nickyname(ExcelReader.randomColumn(resultMap, "receiver_nickyname"));msg.setReceiver_ip(ExcelReader.randomColumn(resultMap, "receiver_ip"));msg.setReceiver_account(ExcelReader.randomColumn(resultMap, "receiver_account"));msg.setReceiver_os(ExcelReader.randomColumn(resultMap, "receiver_os"));msg.setReceiver_phone_type(ExcelReader.randomColumn(resultMap, "receiver_phone_type"));msg.setReceiver_network(ExcelReader.randomColumn(resultMap, "receiver_network"));msg.setReceiver_gps(ExcelReader.randomColumn(resultMap, "receiver_gps"));msg.setReceiver_sex(ExcelReader.randomColumn(resultMap, "receiver_sex"));msg.setMsg_type(ExcelReader.randomColumn(resultMap, "msg_type"));msg.setDistance(ExcelReader.randomColumn(resultMap, "distance"));msg.setMessage(ExcelReader.randomColumn(resultMap, "message"));// 3. 注意时间使用系统当前时间return msg;}
}

生成rowkey

  1. ROWKEY = MD5Hash_发件人账号_收件人账号_消息时间戳
  2. MD5Hash.getMD5AsHex生成MD5值,为了缩短rowkey,取前8位
// 根据Msg实体对象生成rowkeypublic static byte[] getRowkey(Msg msg) throws ParseException {//// ROWKEY = MD5Hash_发件人账号_收件人账号_消息时间戳//// 使用StringBuilder将发件人账号、收件人账号、消息时间戳使用下划线(_)拼接起来StringBuilder builder = new StringBuilder();builder.append(msg.getSender_account());builder.append("_");builder.append(msg.getReceiver_account());builder.append("_");// 获取消息的时间戳String msgDateTime = msg.getMsg_time();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date msgDate = simpleDateFormat.parse(msgDateTime);long timestamp = msgDate.getTime();builder.append(timestamp);// 使用Bytes.toBytes将拼接出来的字符串转换为byte[]数组// 使用MD5Hash.getMD5AsHex生成MD5值,并取其前8位String md5AsHex = MD5Hash.getMD5AsHex(builder.toString().getBytes());String md5Hex8bit = md5AsHex.substring(0, 8);// 再将MD5值和之前拼接好的发件人账号、收件人账号、消息时间戳,再使用下划线拼接,转换为Bytes数组String rowkeyString = md5Hex8bit + "_" + builder.toString();System.out.println(rowkeyString);return Bytes.toBytes(rowkeyString);}

将随机生成的数据推入到HBase

public static void main(String[] args) throws ParseException, IOException {// 读取Excel文件中的数据Map<String, List<String>> resultMap =ExcelReader.readXlsx("D:\\课程研发\\51.V8.0_NoSQL_MQ\\2.HBase\\3.代码\\momo_chat_app\\data\\测试数据集.xlsx", "陌陌数据");// 生成数据到HBase中// 1. 获取Hbase连接Configuration config = HBaseConfiguration.create();Connection connection = ConnectionFactory.createConnection(config);// 2. 获取HBase表MOMO_CHAT:MSGTable table = connection.getTable(TableName.valueOf("MOMO_CHAT:MSG"));int i = 0;int MAX = 100000;while (i < MAX) {Msg msg = getOneMessage(resultMap);// 3. 初始化操作Hbase所需的变量(列蔟、列名)byte[] rowkey = getRowkey(msg);String cf = "C1";String colMsg_time = "msg_time";String colSender_nickyname = "sender_nickyname";String colSender_account = "sender_account";String colSender_sex = "sender_sex";String colSender_ip = "sender_ip";String colSender_os = "sender_os";String colSender_phone_type = "sender_phone_type";String colSender_network = "sender_network";String colSender_gps = "sender_gps";String colReceiver_nickyname = "receiver_nickyname";String colReceiver_ip = "receiver_ip";String colReceiver_account = "receiver_account";String colReceiver_os = "receiver_os";String colReceiver_phone_type = "receiver_phone_type";String colReceiver_network = "receiver_network";String colReceiver_gps = "receiver_gps";String colReceiver_sex = "receiver_sex";String colMsg_type = "msg_type";String colDistance = "distance";String colMessage = "message";// 4. 构建put请求Put put = new Put(rowkey);// 5. 挨个添加陌陌消息的所有列put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colMsg_time), Bytes.toBytes(msg.getMsg_time()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_nickyname), Bytes.toBytes(msg.getSender_nickyname()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_account), Bytes.toBytes(msg.getSender_account()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_sex), Bytes.toBytes(msg.getSender_sex()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_ip), Bytes.toBytes(msg.getSender_ip()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_os), Bytes.toBytes(msg.getSender_os()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_phone_type), Bytes.toBytes(msg.getSender_phone_type()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_network), Bytes.toBytes(msg.getSender_network()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colSender_gps), Bytes.toBytes(msg.getSender_gps()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_nickyname), Bytes.toBytes(msg.getReceiver_nickyname()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_ip), Bytes.toBytes(msg.getReceiver_ip()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_account), Bytes.toBytes(msg.getReceiver_account()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_os), Bytes.toBytes(msg.getReceiver_os()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_phone_type), Bytes.toBytes(msg.getReceiver_phone_type()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_network), Bytes.toBytes(msg.getReceiver_network()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_gps), Bytes.toBytes(msg.getReceiver_gps()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colReceiver_sex), Bytes.toBytes(msg.getReceiver_sex()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colMsg_type), Bytes.toBytes(msg.getMsg_type()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colDistance), Bytes.toBytes(msg.getDistance()));put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(colMessage), Bytes.toBytes(msg.getMessage()));// 6. 发起put请求table.put(put);// 显示进度++i;System.out.println(i + " / " + MAX);}table.close();connection.close();}

这里写入数据的数量为10w,可以看到这个请求是均匀分布在region中的。

实现getMessage数据服务接口

使用scan + filter实现的

  1. 构建scan对象
  2. 构建4个filter(开始日期查询、结束日期查询、发件人、收件人)
  3. 构建一个Msg对象列表
  public List<Msg> getMessage(String date, String sender, String receiver) throws Exception {// 1. 构建scan对象Scan scan = new Scan();// 构建两个带时分秒的日期字符串String startDateStr = date + " 00:00:00";String endDateStr = date + " 23:59:59";// 2.  构建用于查询时间的范围,例如:2020-10-05 00:00:00 – 2020-10-05 23:59:59// 3. 构建查询日期的两个Filter,大于等于、小于等于,此处过滤单个列使用SingleColumnValueFilter即可。SingleColumnValueFilter startDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1"), Bytes.toBytes("msg_time"), CompareFilter.CompareOp.GREATER_OR_EQUAL, new BinaryComparator(Bytes.toBytes(startDateStr)));SingleColumnValueFilter endDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1"), Bytes.toBytes("msg_time"), CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes(endDateStr)));// 4.   构建发件人FilterSingleColumnValueFilter senderFilter = new SingleColumnValueFilter(Bytes.toBytes("C1"), Bytes.toBytes("sender_account"), CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(sender)));// 5.  构建收件人FilterSingleColumnValueFilter receiverFilter = new SingleColumnValueFilter(Bytes.toBytes("C1"), Bytes.toBytes("receiver_account"), CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(receiver)));// 6.    使用FilterList组合所有FilterFilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, startDateFilter, endDateFilter, senderFilter, receiverFilter);// 7.    设置scan对象filterscan.setFilter(filterList);// 8.  获取HTable对象,并调用getScanner执行Table table = connection.getTable(TableName.valueOf("MOMO_CHAT:MSG"));ResultScanner resultScanner = table.getScanner(scan);// 9.   获取迭代器,迭代每一行,同时迭代每一个单元格Iterator<Result> iterator = resultScanner.iterator();// 创建一个列表,用于保存查询出来的消息ArrayList<Msg> msgList = new ArrayList<>();while (iterator.hasNext()) {// 每一行查询出来的数据都是一个Msg对象Result result = iterator.next();Msg msg = new Msg();// 获取rowkeyString rowkey = Bytes.toString(result.getRow());// 单元格列表List<Cell> cellList = result.listCells();for (Cell cell : cellList) {// 根据当前的cell单元格的列名来判断,设置对应的字段String columnName = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());if (columnName.equals("msg_time")) {msg.setMsg_time(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_nickyname")) {msg.setSender_nickyname(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_account")) {msg.setSender_account(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_sex")) {msg.setSender_sex(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_ip")) {msg.setSender_ip(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_os")) {msg.setSender_os(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_phone_type")) {msg.setSender_phone_type(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_network")) {msg.setSender_network(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("sender_gps")) {msg.setSender_gps(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_nickyname")) {msg.setReceiver_nickyname(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_ip")) {msg.setReceiver_ip(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_account")) {msg.setReceiver_account(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_os")) {msg.setReceiver_os(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_phone_type")) {msg.setReceiver_phone_type(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_network")) {msg.setReceiver_network(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_gps")) {msg.setReceiver_gps(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("receiver_sex")) {msg.setReceiver_sex(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("msg_type")) {msg.setMsg_type(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("distance")) {msg.setDistance(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if (columnName.equals("message")) {msg.setMessage(Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}}msgList.add(msg);}// 关闭资源resultScanner.close();table.close();return msgList;}

先执行下这个shell看下结果

 scan 'MOMO_CHAT:MSG' , {COLUMNS => ['C1:sender_account', 'C1:receiver_account', 'C1:msg_time'], FILTER => "SingleColumnValueFilter('C1', 'sender_account', =, 'binary:13514684105') AND SingleColumnValueFilter('C1', 'receiver_account', = , 'binary:13647128512')"}

最后附上代码地址:https://github.com/fafeidou/momo_chat_app

Excel数据导入到hbase实战相关推荐

  1. matlab在曲线给命名,matlab 利用xlsread画图,怎么将一组excel数据导入,通过matlab作图...

    Matlab 循环 for 语句 xlsread EXCEL表格数据导入 画图 Matlab的 xlsread() 函数可以将Excel数据到matlab工作空间,然后就可以根据读入据作图.下面给出操 ...

  2. 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...

     本文目录: (一)背景 (二)数据库数据导入到Excel的方法比较    (三)SSIS的简介    (四)数据库中存储过程示例(SSIS应用需要) (五)Excel模板的制作(这步这么简单,稍微介 ...

  3. 批量Excel数据导入Oracle数据库

    由于一直基于Oracle数据库上做开发,因此常常会需要把大量的Excel数据导入到Oracle数据库中,其实如果从事SqlServer数据库的开发,那么思路也是一样的,本文主要介绍如何导入Excel数 ...

  4. python将EXCEL数据导入数据库时日期型数据变成数字并加.0的问题一行代码解决方案方案

    [问题描述]:python将EXCEL数据导入数据库时日期变成文本型数据并显示为数字格式 [解决方案] 数据源: codes: #!/usr/bin/python3 -- coding: utf-8 ...

  5. 效率最高的Excel数据导入续---SSIS Package包制作图解全过程

    目的:本文主要是详细讲解SSIS Package包的制作过程 本人买过的一张盗版windows 2003操作系统光盘上,上面自带有很详细的图文介绍,也就是傻瓜版的系统安装图解.因此,本文打算也是采用那 ...

  6. python接入excel_使用python将excel数据导入数据库过程详解

    因为需要对数据处理,将excel数据导入到数据库,记录一下过程. 使用到的库:xlrd 和 pymysql (如果需要写到excel可以使用xlwt) 直接丢代码,使用python3,注释比较清楚. ...

  7. 怎么将excel数据导入到datagridview中

    本人小白,想要实现EXCEL文件中的数据导入到datagridview中,EXCEL中的数据是多行多列,行数和列数不确定,如何实现导入到datagridview中显示,具体的界面如下: 两个butto ...

  8. 使用python将excel数据导入数据库

    https://www.cnblogs.com/longbigbeard/p/9309180.html 因为需要对数据处理,将excel数据导入到数据库,记录一下过程. 使用到的库:xlrd 和 py ...

  9. matlab打开矩阵表,如何将Excel数据导入MATLAB中?:EXCLE中通过矩阵表输出选项

    怎么把matlab中处理的数据存入到excel中 可以直接xlswrite命令. data=randn(100,1); % data为需要存储的数 xlswrite('D:\write2Excel.x ...

最新文章

  1. 针对IE6\7\8\9\10浏览器的CSS hack大全详解
  2. 讲讲数据分析中的同期群模型
  3. 新的一年到来了,我要做的第一件事是放弃……
  4. pythonの鉴黄之路(一)——YCbCr简易版鉴黄脚本
  5. Facebook研究院院长:AI不会取代人类
  6. VS2012发布网站IIS配置
  7. win10怎么设置计算机密码怎么设置,win10如何设置开机密码|win10设置登陆密码和账户的方法...
  8. 南宁:“数字城管”让智慧城市建设提质提速
  9. 通过http网页链接下载单词音频文件
  10. 17个改变世界的数学公式!
  11. 在线License管理系统(支持离线授权)
  12. SNK,作为程序后缀的时候,是.net中的强密匙加密文件
  13. QT 错误:Unable to create a debugging engine解决
  14. MFC 对话框添加背景图
  15. c语言以16进制输出大写字母,C语言二进制、八进制、十六进制整数书写和输出...
  16. plc学习入门有什么技巧
  17. 信噪比(一些概念,公式推导,实验分析)
  18. 不只是A/B测试:多臂老虎机赌徒实验
  19. Newtonsoft.Json.JsonConvert.SerializeObject()
  20. 抽象语法树在 JavaScript 中的应用

热门文章

  1. VC中GetLastErro返回的错误码
  2. [typescript]请使用“以管理员身份运行”选项启动 Windows PowerShell。要更改当前用户的执行策略,请运行 “Set-ExecutionPolicy -Scope Curren
  3. 网站关键词的选择和优化设置技巧
  4. postfix mysql 虚拟用户_postfix+extmail+mysql虚拟用户邮件体系的搭建
  5. 如何在线下载无水印视频
  6. 【搜索+DP】codevs1066-引水入城
  7. 日剧有哪些好看点的-推荐两部
  8. 1024_回首2022我做了啥
  9. DLT645协议解析(二)---07协议数据帧结构解析
  10. Google Earth 背后的故事