hbase 服务化文档

2019-08-01  本文已影响0人  pcgreat

hbase 单独抽出平台 说白了 就是解决 hbase put ,scan 操作 ,开发比较吃力 ,不优雅等问题。
要做的事情
1 . hbase 方法 做好 告警
2 . hbase 连接池设置
3 . hbase 连接超时时间配置等
4 . 如果能提供hue那样的脚本查询 那就好了 (这能解决很多问题)
5 . 提供业务同学查询能力 ,完全屏蔽hbase 操作 不需要让他们接触 Scan 创建 ,find 方法的调用等等
6. 如果 基于sql 甚至可以做到 es ,hbase , mysql , 统一数据访问平台 ,基于配置中心 ,sql , 业务只需要传 对应的模板id ,参数 , 便能统一返回 。这种方式 优点 很多 ,数据访问 的审核(delete ,drop ,不能update别人业务模块数据 ) ,sql 性能审核和调优 ,数据库的隔离 (业务是对于数据库不知情的),数据迁移等问题 。 这种情况 我推荐 互联网的公司 比较合适 ,他们迭代周期短 ,需求变化频繁,读写并发 要求高 ,基于模板的方式 ,能够快速变更业务 ,甚至连 mybatis 都不用接触 。 缺点就是 需要有能力的人 维护 , 需要有能力的人开发 , 。对于项目型 的公司 通过mybatis 访问 phoenix + hbase 也是 一种好的方法 。

下面 主要 两个方式 , 一个基于 接口 方向 , 一个 基于 sql 方向
基于 定义接口方式 比如像 getListByPrefixRowkey
问题1
本身 filter 还是挺多的 为每个filter 方法 ,创建一个find 方法,那显然是累死人的做法 ,业务同学估计也不爽


image.png
image.png

问题2
filter list 形式 , filter 那么多 组合的形式 更是多

针对上面两个问题 mop-hbase-template 有一定的解决
但是 基本是针对ValueFilter 来做的

image.png

但是 项目实际 情况 有很多都是
RowFilter + RowFilter


image.png

RowFilter + PrefixFilter


image.png

PrefixFilter + PageFilter


image.png

ColumnPrefixFilter


image.png

所以这一块 需要单独的设计 ,
设计方案1 .简单方法为上面每个例子提供方法
比如
RowFilter + RowFilter
getListByRowFilters 同理
PrefixFilter + PageFilter
getListByRowFilterAndPageFilter

RowFilter 需要的参数 需要封装 SubstringComparator ,RegexStringComparator,BinaryPrefixComparator 以及
CompareFilter.CompareOp.EQUAL等
PrefixFilter 需要的参数 prefix
PageFilter 需要的参数 pageSize
ColumnPrefixFilter 需要的参数 prefix
这样设计的话 需要 将RowFilter ,PrefixFilter ,PageFilter 进行封装
感觉上 还是没有屏蔽hbase

设计方案二 已语义的方法 去做这件事情,但这种方法接口会非常多
getListByPrefixRowkeyAndRegexRowKey
getListByPrefixRowkeyAndPageFilter

为什么 我们不能提供一个 更简单的方法呢
类似于 hue hbase的脚本 或者 直接 让业务方 传sql 呢 比如说 phoenix
1 . 同样能解决 hbase put ,scan 操作 ,开发比较吃力 ,不优雅的问题
2 . sql 谁都会
但是 phoenix 性能是否能搞定呢 。
基于他的例子 表结构如下图

CREATE TABLE IF NOT EXISTS %s (HOST CHAR(2) NOT NULL,
DOMAIN VARCHAR NOT NULL, 
FEATURE VARCHAR NOT NULL,
DATE DATE NOT NULL,
USAGE.CORE BIGINT,
USAGE.DB BIGINT,
STATS.ACTIVE_VISITOR INTEGER
CONSTRAINT PK PRIMARY KEY (HOST, DOMAIN, FEATURE, DATE))  
SPLIT ON   ('CSGoogle','CSSalesforce','EUApple','EUGoogle','EUSalesforce','NAApple','NAGoogle','NASalesforce')

而 实际 hbase 表结构 如下图

hbase(main):005:0> scan  'PERFORMANCE_20000000' , { FILTER=>" RowFilter(=,'regexstring:Apple.com')" ,LIMIT=>5}
ROW                                                                  COLUMN+CELL                                                                                                                                                                                              
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDC\xCEh                 column=STATS:\x80\x0D, timestamp=1564741554988, value=\x80\x00&S                                                                                                                                         
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDC\xCEh                 column=USAGE:\x00\x00\x00\x00, timestamp=1564741554988, value=x                                                                                                                                          
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDC\xCEh                 column=USAGE:\x80\x0B, timestamp=1564741554988, value=\x80\x00\x00\x00\x00\x00\x01\x09                                                                                                                   
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDC\xCEh                 column=USAGE:\x80\x0C, timestamp=1564741554988, value=\x80\x00\x00\x00\x00\x00\x05\xCA                                                                                                                   
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\x1EX                 column=STATS:\x80\x0D, timestamp=1564741555106, value=\x80\x00\x1EM                                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\x1EX                 column=USAGE:\x00\x00\x00\x00, timestamp=1564741555106, value=x                                                                                                                                          
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\x1EX                 column=USAGE:\x80\x0B, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x00\xA0                                                                                                                   
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\x1EX                 column=USAGE:\x80\x0C, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x07A                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDEp`                    column=STATS:\x80\x0D, timestamp=1564741555106, value=\x80\x00\x01\x1F                                                                                                                                   
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDEp`                    column=USAGE:\x00\x00\x00\x00, timestamp=1564741555106, value=x                                                                                                                                          
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDEp`                    column=USAGE:\x80\x0B, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x00)                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDEp`                    column=USAGE:\x80\x0C, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x03f                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\xED`                 column=STATS:\x80\x0D, timestamp=1564741555106, value=\x80\x00\x0DW                                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\xED`                 column=USAGE:\x00\x00\x00\x00, timestamp=1564741555106, value=x                                                                                                                                          
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\xED`                 column=USAGE:\x80\x0B, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x019                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDE\xED`                 column=USAGE:\x80\x0C, timestamp=1564741555106, value=\x80\x00\x00\x00\x00\x00\x02(                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDF\xB4\x98              column=STATS:\x80\x0D, timestamp=1564741555156, value=\x80\x00\x0EQ                                                                                                                                      
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDF\xB4\x98              column=USAGE:\x00\x00\x00\x00, timestamp=1564741555156, value=x                                                                                                                                          
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDF\xB4\x98              column=USAGE:\x80\x0B, timestamp=1564741555156, value=\x80\x00\x00\x00\x00\x00\x01\x06                                                                                                                   
 CSApple.com\x00Dashboard\x00\x80\x00\x01lQ\xDF\xB4\x98              column=USAGE:\x80\x0C, timestamp=1564741555156, value=\x80\x00\x00\x00\x00\x00\x01[   

 HOST, DOMAIN, FEATURE, DATE 构成了 rowkey  

我发现了 个问题 2000 w 的数据量

select  *  from PERFORMANCE_20000000 where DOMAIN = 'Apple.com'  limit 5

+-------+------------+------------+--------------------------+-------+-------+-----------------+
| HOST  |   DOMAIN   |  FEATURE   |           DATE           | CORE  |  DB   | ACTIVE_VISITOR  |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| CS    | Apple.com  | Dashboard  | 2019-08-02 10:25:21.000  | 265   | 1482  | 9811            |
| CS    | Apple.com  | Report     | 2019-10-14 07:19:58.000  | 302   | 1628  | 5185            |
| EU    | Apple.com  | Dashboard  | 2019-08-02 10:25:26.000  | 346   | 981   | 673             |
| EU    | Apple.com  | Report     | 2019-10-14 02:35:55.000  | 268   | 325   | 989             |
| NA    | Apple.com  | Dashboard  | 2019-08-02 10:24:59.000  | 343   | 907   | 4117            |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
5 rows selected (10.726 seconds)

需要10 s 时间
而基于 hbase shell 只需要 36ms
scan 'PERFORMANCE_20000000' , { FILTER=>" RowFilter(=,'regexstring:Apple')" ,LIMIT=>5} 而且 返回数据不同 。
也就是说 phoenix 不是 按照 hbase shell 这种方式去执行的 。 为什么呢
是不是SPLIT ON ('CSGoogle','CSSalesforce','EUApple','EUGoogle','EUSalesforce','NAApple','NAGoogle','NASalesforce') 手动设计分区的原因呢
好 我们可以在创建一张测试表 PERFORMANCE2_20000000 ,数据量 只有200w ,没有手动分区 。 测试结果 性能是可以的

select     *  from PERFORMANCE_2500000 where  DOMAIN = 'Apple.com'     limit 5  ;
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| HOST  |   DOMAIN   |  FEATURE   |           DATE           | CORE  |  DB   | ACTIVE_VISITOR  |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| CS    | Apple.com  | Dashboard  | 2019-08-07 07:15:20.000  | 467   | 1178  | 612             |
| NA    | Apple.com  | Report     | 2019-08-09 03:01:27.000  | 418   | 1196  | 6805            |
| CS    | Apple.com  | Dashboard  | 2019-08-07 07:15:33.000  | 465   | 1216  | 1192            |
| NA    | Apple.com  | Report     | 2019-08-09 03:01:58.000  | 34    | 608   | 9394            |
| CS    | Apple.com  | Dashboard  | 2019-08-07 07:16:39.000  | 219   | 589   | 8231            |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
5 rows selected (0.029 seconds)

创建一张新的表 和 hbase 结构完全一样 ,数据量250w 。ok 完全可以


image.png

以上问题 理论上 应该是 phoenix 在多主键 且查询 无第一主键的情况 选择错误的执行计划 ,而如果 按hbase 表单结构设计则无此问题 。

那我们换一种想法 , phoenix 用了数据库思想做了 些他不该做的事情 那么 ,我们可不可以 去掉它的执行计划 ,按hbase的方式来呢 。官网 有这个例子 。

Use the SKIP_SCAN hint to force a skip scan to be performed on the query when it otherwise would not be. This option may improve performance if a query does not include the leading primary key column, but does include other, very selective primary key columns.

0: jdbc:phoenix:localhost:2181:/hbase> select  /*+ SKIP_SCAN  */   *  from PERFORMANCE_20000000 where  DOMAIN = 'Apple.com'     limit 5 
. . . . . . . . . . . . . . . . . . .> ;
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| HOST  |   DOMAIN   |  FEATURE   |           DATE           | CORE  |  DB   | ACTIVE_VISITOR  |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| CS    | Apple.com  | Dashboard  | 2019-08-06 02:45:34.000  | 136   | 95    | 174             |
| EU    | Apple.com  | Dashboard  | 2019-08-06 02:46:06.000  | 432   | 1691  | 4943            |
| NA    | Apple.com  | Dashboard  | 2019-08-06 02:47:03.000  | 408   | 1977  | 9440            |
| CS    | Apple.com  | Dashboard  | 2019-08-06 02:46:57.000  | 71    | 494   | 2306            |
| EU    | Apple.com  | Dashboard  | 2019-08-06 02:46:18.000  | 202   | 1097  | 6735            |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
5 rows selected (0.068 seconds)
0: jdbc:phoenix:localhost:2181:/hbase>   select  /*+ SKIP_SCAN  +NO_INDEX  */   *  from PERFORMANCE_20000000 where  DOMAIN = 'Apple.com'     limit 5  ;
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| HOST  |   DOMAIN   |  FEATURE   |           DATE           | CORE  |  DB   | ACTIVE_VISITOR  |
+-------+------------+------------+--------------------------+-------+-------+-----------------+
| CS    | Apple.com  | Dashboard  | 2019-08-06 02:45:34.000  | 136   | 95    | 174             |
| EU    | Apple.com  | Dashboard  | 2019-08-06 02:46:06.000  | 432   | 1691  | 4943            |
| NA    | Apple.com  | Dashboard  | 2019-08-06 02:47:03.000  | 408   | 1977  | 9440            |
| CS    | Apple.com  | Dashboard  | 2019-08-06 02:46:57.000  | 71    | 494   | 2306            |
| EU    | Apple.com  | Dashboard  | 2019-08-06 02:46:18.000  | 202   | 1097  | 6735            |
+-------+------------+------------+--------------------------+-------+-------+-----------------+


阿里同学文章写得很详细
https://yq.aliyun.com/articles/703818?spm=a2c4e.11155435.0.0.c1434db44lHjaV
还有篇文章 写得也是极好
https://blog.csdn.net/rlnLo2pNEfx9c/article/details/78692969

然后
mop-hbase-template 不是基于 spring boot hbase template 来的
而且使用的hbase-client版本为0.96

上一篇下一篇

猜你喜欢

热点阅读