scan-get

  • get:
    • 按照RowKey获取唯一一条记录。get的方法处理分两种:设置了ClosestRowBefore和没有设置ClosestRowBefore的RowLock。主要用来保证行的事务性,即每个get是以一个row来标记的。
    • get 后面可以跟table表名,rowkey,以及column,value.但是如果想通过get直接获取一个表中的全部数据是做不到的,这种情况就要用到另外一个命令scan。
  • scan:
    • scan的用法很多,可以直接扫描全表信息,也可以通过指定条件来显示我们所需要获取的数据
    • 按照指定的条件获取一批记录。
    • 可以通过setCaching和setBatch方法提高速度;
      可以通过setStartRow与setEndRow来限定范围;
      可以通过setFilter方法添加过滤器,这也是分页、多条件查询的基础
--==========================================================================
---1. get 获取table中rowkey语句 于 Scan获取table中rowkey语句
--【get】
hbase(main):011:0> get 'liupeng:employee','1001'
COLUMN                                  CELL
 contect:mail                           timestamp=1522202414649, value=liupliup@cn.ibm.com
 contect:phone                          timestamp=1522202430196, value=15962459503
 group:number                           timestamp=1522202455929, value=1
 info:age                               timestamp=1522202371257, value=34
 info:name                              timestamp=1522202364156, value=liupeng

--【Scan】
hbase(main):010:0> scan 'liupeng:employee',FILTER=>"PrefixFilter('1001')"
ROW                                     COLUMN+CELL
 1001                                   column=contect:mail, timestamp=1522202414649, value=liupliup@cn.ibm.com
 1001                                   column=contect:phone, timestamp=1522202430196, value=15962459503
 1001                                   column=group:number, timestamp=1522202455929, value=1
 1001                                   column=info:age, timestamp=1522202371257, value=34
 1001                                   column=info:name, timestamp=1522202364156, value=liupeng
1 row(s) in 0.0590 seconds

---总结:
--Scan的结果包含了rowkey本身。而get获取到的信息不包含rowkey的值。
--另外,get的column于cell是分开的。而Scan是2者结合在一起的,Scan中FILTER过滤“PrefixFilter”关键字是用来筛选rowkey的。

--==========================================================================
--2. get于Scan获取table中单条数据信息中的区别
--把table中rowkey为1001,元素为'159'的信息查询出来
COLUMN                          CELL                                                                                     
 info:phone                     timestamp=1527914569028, value=15962459503                                               
1 row(s) in 0.0320 seconds

hbase(main):230:0> scan "liupeng:employee",FILTER=>"PrefixFilter('1001')AND ValueFilter(=,'substring:159')"
ROW                             COLUMN+CELL                                                                            
 1001                           column=info:phone, timestamp=1527914569028, value=15962459503                            
1 row(s) in 0.1010 seconds

--==========================================================================
--3. Scan模糊查询直接找到了只要包含159的字段的值就全部显示出来。
--而get的语法如下所视必须指定rowkey的基础上才可以查询columns。
--这就需要对rowkey定义的时候,考虑全面的涉及才可以做到。因此从这点来看Scan的方法个人认为比get获取信息更加的便捷。
hbase(main):026:0> scan 'liupeng:employee',FILTER=>"ValueFilter(=,'substring:159')"
ROW                                     COLUMN+CELL
 1001                                   column=contect:phone, timestamp=1522202430196, value=15962459503
 1002                                   column=contect:phone, timestamp=1522202527866, value=15977634464
 
--==========================================================================
-- 4.Scan方法可以不用指定rowkey检索的情况下直接找valuse值。
--更具体点说也就是我们要找的哪个column中的哪个value值。get方法是无法做到这一点的。
--ColumnPrefixFilter('列名')

hbase(main):038:0> scan 'liupeng:employee',FILTER=>"ColumnPrefixFilter('name')"
ROW                                     COLUMN+CELL
 1001                                   column=info:name, timestamp=1522202364156, value=liupeng
 1002                                   column=info:name, timestamp=1522202474669, value=Jack_Ma
 1003                                   column=info:name, timestamp=1522202561029, value=kevin_shi
3 row(s) in 0.0210 seconds

##注释:ColumnPrefixFilter代表指定具体哪一个column(key(info)对应的value(name))。

--==========================================================================
--5. Scan方法方便在于它可以随意指定rowkey,column以及value的值来进行查找。
--还可以结合AND,ORD等条件语句并用来找到自己想要的数据。
hbase(main):060:0> scan 'liupeng:employee',FILTER=>"ColumnPrefixFilter('ph') AND ValueFilter(=,'substring:15962')OR ValueFilter(=,'substring:186')"
ROW                                                  COLUMN+CELL
 1001                                                column=contect:phone, timestamp=1522202430196, value=15962459503
 1003                                                column=contect:phone, timestamp=1522202605976, value=18665851263
2 row(s) in 0.0170 seconds

--==========================================================================
--6. 通过SingleColumnValueFilter类方法指定检索值列举出检索值对应的所有列及value数据
-- SingleColumnValueFilter类还提供正则表达式查询方法。可以通过模糊查询来查找对应的rowkeys,columns以及values。
hbase(main):244:0> scan "liupeng:employee",{FILTER=>"SingleColumnValueFilter('info','name',=,'regexstring:liu')"}
ROW                             COLUMN+CELL                                                                              
 1001                           column=contect:mail, timestamp=1527231141046, value=liupliup@cn.ibm.com                  
 1001                           column=info:address, timestamp=1527753987327, value=shanghai                             
 1001                           column=info:age, timestamp=1527231097033, value=34                                       
 1001                           column=info:name, timestamp=1527231081262, value=liupeng                                 
 1001                           column=info:phone, timestamp=1527914569028, value=15962459503                            
 1004                           column=contect:mail, timestamp=1527473497956, value=lqdong@jingdong.com                  
 1004                           column=info:address, timestamp=1527755135174, value=shenzhen                             
 1004                           column=info:age, timestamp=1527473477124, value=40                                       
 1004                           column=info:name, timestamp=1527415665182, value=liuqiangdong                            
2 row(s) in 0.0080 seconds

三、方舟HBase Rowkey设计实战

在实际的设计中我们可能更多的是结合多种设计方法来实现Rowkey的最优化设计,

比如设计订单状态表时使用:Rowkey: reverse(order_id) + (Long.MAX_VALUE – timestamp),

这样设计的好处一是通过reverse订单号避免Region热点,二是可以按时间倒排显示

结合易观方舟使用HBase作为事件(事件指的的终端在APP中发生的行为,比如登录、下单等等统称事件(event))的临时存储(HBase只存储了最近10分钟的热数据)来举例:

设计event事件的Rowkey为:两位随机数Salt + eventId + Date + kafka的Offset

这样设计的好处是:

设计加盐的目的是为了增加查询的并发性,假如Salt的范围是0~n,那我们在查询的时候,可以将数据分为n个split同时做scan操作。经过我们的多次测试验证,增加并发度能够将整体的查询速度提升5~20倍以上。随后的eventId和Date是用来做范围Scan使用的。在我们的查询场景中,大部分都是指定了eventId的,因此我们把eventId放在了第二个位置上,同时呢,eventId的取值有几十个,通过Salt + eventId的方式可以保证不会形成热点。在单机部署版本中,HBase会存储所有的event数据,所以我们把date放在rowkey的第三个位置上以实现按date做scan,批量Scan性能甚至可以做到毫秒级返回。

这样的rowkey设计能够很好的支持如下几个查询场景:

1、全表scan

在这种情况下,我们仍然可以将全表数据切分成n份并发查询,从而实现查询的实时响应。

2、只按照event_id查询

3、按照event_id和date查询

此外易观方舟也使用HBase做用户画像的标签存储方案,存储每个app的用户的人口学属性和商业属性等标签信息,由于其设计的更为复杂,后续会另起篇幅详细展开。

最后我们顺带提下HBase的表设计,HBase表设计通常可以是宽表(wide table)模式,即一行包括很多列。同样的信息也可以用高表(tall table)形式存储,通常高表的性能比宽表要高出 50%以上,所以推荐大家使用高表来完成表设计。表设计时,我们也应该要考虑HBase数据库的一些特性:

1、在HBase表中是通过Rowkey的字典序来进行数据排序的

2、所有存储在HBase表中的数据都是二进制的字节

3、原子性只在行内保证,HBase不支持跨行事务

4、列族(Column Family)在表创建之前就要定义好

  1. 列族中的列标识(Column Qualifier)可以在表创建完以后动态插入数据时添加

四、总结

在做Rowkey设计时,请先考虑业务是读比写多、还是读比写少,HBase本身是为写优化的,即便是这样,也可能会出现热点问题,而如果我们读比较多的话,除了考虑以上Rowkey设计原则外,还可以考虑HBase的Coprocessor甚至elastic search结合的方法,无论哪种方式,都建议做实际业务场景下数据的压力测试以得到最优结果。
————————————————
转载于 代立冬的文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值