目录
落地案例架构
难点
RowKey
RowKey设计原则
热点问题
Salting
Hashing
Reversing
典型设计
查询卖家某个时间内交易记录
时间搜索条件
查询最近操作
查询一段时间内的数据
HBase读优化
Scan缓存
scan.setBlockCache(false)
落地案例架构
原始数据->kafka->Spark->HBase->Spark ML分析
可以看到HBase作为储存介质,Spark进行分析
难点
RowKey
1)唯一性,要保证唯一的row方便排序以及查询
2)复杂查询 解决方案:使用NewSql Phoeinx支持二级索引,方便复杂数据查询
是由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)
禁用缓存
避免将其他实时业务数据挤出,造成读延时毛刺