美文网首页
hbase 服务化文档

hbase 服务化文档

作者: pcgreat | 来源:发表于2019-08-01 14:54 被阅读0次

    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

    相关文章

      网友评论

          本文标题:hbase 服务化文档

          本文链接:https://www.haomeiwen.com/subject/wzptdctx.html