最近在项目开发中遇到了一个使用hbase计数器对实时数据进行计数发生的问题。花了老长时间,必须得记录下来,希望能帮到一些开发者。
业务背景是需要计算各个车场的车流进出的数据。在这个场景下想到用HBASE的incrementColumnValue方法会很好的对车流的进出进行一个计数,最后达到一个实时计算出车流各项指标的效果。
首先你以为hbase与hive的外部表集成很友好吗?并不是!!!
接下来看一下问题
之前直接在hive当中建一张hbase的外部表,建表语句如下
CREATE EXTERNAL TABLE if not exists ods_mixc.ta_cstmr_car_flow_for_15min_ext
(
rowkey string comment 'hbase,rowkey',
innum string comment '进口数量',
outnum string comment '出口数量'
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping'=":key,
cf1:innum,
cf1:outnum"
)
TBLPROPERTIES("hbase.table.name" = "ods_mixc:mixc_cstmr_car_flow_for_15min_data");
紧接着调用了hbase计数器,把数据直接写到hbase里面,就是这个方法 -- table.incrementColumnValue,
使用到的人会发现,最后一个参数只允许传一个long类型。
接下来会在hbase看到自己插入的数据。
long类型的值被转换成这样第一次这样用hbase的人会不会觉得奇怪,其实这个是没有问题的。hbase由于暂时只支持String类型数据的存取,所以自增的long值会在hbase中转换成这样,显示出这个样子。
可以通过这个帖子进行详细了解
https://www.cnblogs.com/zhengrunjian/p/4535273.html
这个value虽然没有问题,但是我们总不可能肉眼去判断这个值我们是否计算正确。之前建的hive表就派上了用场。
再看下我们hbase对应的hive表。之前我们为什么要建这个外部表呢,就是为了能够直观的看到hbase的二进制表示,就如上图。
这就是之前困扰我很久的问题。
首先如上建的外部表,最后数据在hive当中显示是什么样的,可以看下图
可以看到,明明写了数据进入hbase,为什么hive中显示是空字符串呢(如果是null的话,会显示null)
找了半天,考虑是不是hive得外部表有问题。接下来换了一个建表语句
注意这里不需要删除之前建的hbase内部表!!!只需要删除hive外部表
CREATE EXTERNAL TABLE if not exists ods_mixc.ta_cstmr_car_flow_for_15min_ext
(
rowkey string comment 'hbase,rowkey',
innum Integer comment '进口数量', -- 数据类型做了修改
outnum Integer comment '出口数量'
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping'=":key,
cf1:innum#b, --至于这里为什么要加#b,可以参考这个博客https://blog.csdn.net/piaole361/article/details/78597097
cf1:outnum#b"
)
TBLPROPERTIES("hbase.table.name" = "ods_mixc:mixc_cstmr_car_flow_for_15min_data");
此时查到hive表的数据是
之前我已经对innum做了+1操作,但是显示是0。觉得很奇怪,并且我武断的认为hive的显示没问题,于是方向被绕道解决
代码问题上,因此在incrementColumnValue方法上纠结,但是这里其实做的操作很少,就是调用hbase的api。
后面还是觉得代码应该没有问题,重新回到建表语句上来,这个是将建表语句改成这个
同样,hbase内部表不需要删除(提醒下刚接触hbase的人,像我这样~~~)
CREATE EXTERNAL TABLE if not exists ods_mixc.ta_cstmr_car_flow_for_15min_ext
(
rowkey string comment 'hbase,rowkey',
innum bigint comment '进口数量', --改成bigint
outnum bigint comment '出口数量'
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping'=":key,
cf1:innum#b,
cf1:outnum#b"
)
TBLPROPERTIES("hbase.table.name" = "ods_mixc:mixc_cstmr_car_flow_for_15min_data");
最后查到hive中数据显示:
问题解决。
考虑到hive中Integer跟bigint是可以互转的,但是与hbase混搭就出现问题。大家可以自行了解一下原因是什么,这里不做过多介绍,时间紧,难有时间码博客
这次也是实在遇到坑了,希望可以帮助到一些人,也请各位指点一二
需求实现主要用到的技术:storm+kafka+hbase(存储明细,计算指标,指标存储)+传统数据库(落地)