目录

落地案例架构

难点

RowKey

RowKey设计原则

热点问题

Salting

Hashing

Reversing

典型设计

查询卖家某个时间内交易记录

时间搜索条件

查询最近操作

查询一段时间内的数据

HBase读优化

Scan缓存

scan.setBlockCache(false)


落地案例架构

原始数据->kafka->Spark->HBase->Spark ML分析

可以看到HBase作为储存介质,Spark进行分析

难点

RowKey

1)唯一性,要保证唯一的row方便排序以及查询

2)复杂查询  解决方案:使用NewSql Phoeinx支持二级索引,方便复杂数据查询

hbase rowkey的模糊查询 hbase根据rowkey模糊查询_Max

是由RegionService来保存数据。

3)Region根据RowKey进行排序

读取数据通过RowKey找到Region,所以设计好RowKey重要

 

RowKey设计原则

e.g.  uid+phone+name

支持查询uid,phone,name进行模糊查询

比如:uid = 111 and phone =12?

具体实现方法:通过Scan设置Filter,有点类似正则过滤器

Filter fileter = new SingleColumnValueFilter(Bytes.toBytes("gpsinfo"),
    Bytes.toBytes(column), CompareOp.EQUAL,
    new RegexStringComparator("[2-4]{4}"));
   Scan scan = new Scan();
   scan.setFilter(fileter);

里面有一个比较重要的匹配RegexStringComparator

Like规则:

要求以ABC开头:new RegexStringComparator("^ABC")

 要求以ABC结尾:new RegexStringComparator("ABC$")

 要求包含ABC:new RegexStringComparator("ABC")

 要求包含4位2或3或4的数值:new RegexStringComparator("[2-4]{4}")

参考这篇文章

热点问题

上面也提到Region会根据RowKey进行排序,如果RowKey设计不好的话,某一部分的Region会产生数据热点,导致读写的压力会很大。

解决方案有一下:

Salting

一看是加盐,其实并不是,就是在字符串前加一个混淆一下字符串

e.g. f01234 Salting之后变成 a-f01234

优点:打散data

缺点:增加了读的代价

Hashing

顾名思义:对字符串进行hash,这里使用的是md5转换,subString(md5(设备id),0,X)+设备id 

上面x可以是5或者6

为啥要hash?

有些设备id前一部分是型号,一旦某一批型号出现问题,会造成热点数据,所以进行hash

其次考虑到长度吧,再截断

Reversing

反转,Java本身也有StringBuffer反转方法

有什么用?

类似:aa.com,bb.com,显然他们在HBase存储是不在同一个Region中的,我们可以通过反转将他们储存到一个Region中

比如moc.aa,moc.bb

典型设计

查询卖家某个时间内交易记录

sellerId+timestamp+orderId

或者salt+sellerId+timestamp(salt为随机数)

查询的时候进行RowKey进行模糊查询即可

 

时间搜索条件

uid+Long.Max_value-timestamp

为啥要这样设计?

Region默认排序是从小到大,那么Long.Max_value是不变的,当我们timestamp变大的时候,结果就小了。也就是把最新的排最前面

查询最近操作

start Row [uid][0000..] stopRow [uid][Long.Max_value-endTime]

查询一段时间内的数据

Scan uid startRow  [uid][Long.Max_value-starttime] stopRow  [uid][Long.Max_value-endTime]

 

HBase读优化

Scan缓存

100->500->1000

减少RPC次数

scan.setBlockCache(false)

禁用缓存

避免将其他实时业务数据挤出,造成读延时毛刺