HBase 索引之标签索引特性使用介绍(Tagram)
【简介】
某某购物平台,存储了用户的画像信息,如性别,职业,消费水平,活跃程度,购物类型,起居时间,品牌偏好,颜色偏好,价格偏好等信息,需要根据此类信息完成精准推荐
假设现在需要做这样一个功能,将某类商品精准推荐给女性,职业为IT,消费水平较高,活跃程度较高,喜欢红色的一类人(这一类人可能基于上面的条件随机组合),那么如何快速筛选出这么一类人呢?
可以基于以下几类方案进行实现:
1.传统二级索引方案,如hbase Phoenix实现多维索引的的快速搜索
2.HBase+Solr/ES,HBase存放数据,Solr/ES存放索引
3.自设计多维索引
以上三种方案,
第一种方案,当涉及到多维索引组合时,查询效率低下
第二种方案,不适合频繁更新场景,数据一致性较弱,高价值数据无法有效缓存
第三种方案,涉及大量的二次开发量
上面的三种方案,都不能完美实现业务的要求,以下介绍标签索引方案
基于倒排/位图索引的标签索引技术
我们基于分布式倒排索引/位图索引技术,来构建标签索引,FusionInsight 6.5.1 项目的名称为Tagram,而华为云CloudTable服务里面称为Lemon Bitmap,原理都是类似的,Lemon Bitmap是Tagram的升级版,在使用上更为简单,下面重点介绍如何使用Tagram实现上面的业务需求。
接着我们上面的场景,看看如何实现?
样例数据,数据表只有一个列族I,而且I中存放了所用客户的标签信息,Qualifier名称为标签分类,而Value中存放了标签值
Rowkey | Column Family(I) | |||
uuidexy | sex | profession | favorite | activety |
Male | engeeneer | red | 10 | |
uuidtxy | sex | profession | favorite | activety |
Female | painter | white | 5 | |
uuidzxy | sex | profession | favorite | activety |
Female | engeeneer | white | 7 |
Tagram使用方法
写入静态标签元数据
在已经创建好的标签元数据表中,新增静态标签的元数据定义。
接口定义如下:
TagSourceDataService#addStaticTag(String tagName) throws IOException
TagSourceTable为TagSourceDataService的默认实现类。
样例代码如下:
public void addStaticTag(Connection connection) throws IOException {
// 创建Table对象
TagSourceTable tagSourceTable = new TagSourceTable(connection, tagSourceTableName);
// 插入枚举型标签定义
tagSourceTable.addStaticTag("GENDER:Male");
tagSourceTable.addStaticTag("GENDER:Female");
tagSourceTable.addStaticTag("BLOOD_TYPE:A");
tagSourceTable.addStaticTag("BLOOD_TYPE:B");
tagSourceTable.addStaticTag("BLOOD_TYPE:AB");
tagSourceTable.addStaticTag("BLOOD_TYPE:O");
// 插入布尔型标签定义
tagSourceTable.addStaticTag("CAROWNER");
}
写入动态标签数据
向标签数据表中动态插入新的动态标签的数据。
TagramDataService#dynamicTag(String tagHostId, String tagName, byte[] payload) throws IOException
TagHostTable为TagramDataService的默认实现类。
样例代码如下:
public void putDynamicTagData(Connection connection) { TagHostTable tabHostTable = new TagHostTable(tagDataTableName, connection); try { tabHostTable.dynamicTag("uuidexy", "DTag1", Bytes.toBytes("Other message001")); tabHostTable.dynamicTag("uuidtxy", "DTag2", Bytes.toBytes("Other message101")); tabHostTable.dynamicTag("uuidzxy", "DTag1", Bytes.toBytes("Other message301")); } catch (IOException e) { e.printStackTrace(); } }
说明:
动态标签不需要预先定义即可执行插入操作。
标签查询
通过标签条件可以进行查询标签承载体的功能。
接口定义如下:
TagramDataService#query(QueryRequest request) throws IOException
TagHostTable为TagramDataService的默认实现类。
查询语法表述如下(基于BNF范式)
TQuery ::= ( TClause )+
TClause ::= ["AND", "OR", "NOT"] ([TagType:]TagValue[^Weight] | "(" TQuery ")" )
单标签查询语句
一个标准的标签查询条件的描述应该为:
TagType:TagValue
如果是布尔标签,同属于TagType为$B的标签大类。
如果是动态标签,同属于TagType为$D的标签大类。
操作符及优先级定义
方案中支持如下几种操作符:
AND: AND用来连接两个标签条件且两个标签条件均需要满足。
OR: OR用来连接两个标签条件且只需要两个中的任意一个满足即可。
NOT: NOT是二元操作符,第一个标签条件必须满足, 第二个标签条件不能满足。
( ) : 用来提升某局部组合语句的优先级,可以称作为一个标签组。
^ : 用于查询时指定某标签在查询结果的权重。权重值为0到1000000间的浮点数(float)。不指定的时候,标签的默认权重为1。
public void queryData(Connection connection) {
// 构造查询请求
QueryRequest.Builder requestBuilder = new QueryRequest.Builder();
// 标签条件组合
String condition = "BLOOD_TYPE:A AND $B:CAROWNER AND $D:DTag1";
requestBuilder.setCondition(condition);
// 设置需要返回的结果数量
requestBuilder.setLimit(100);
// 设置这次查询不只是统计结果
requestBuilder.setCountOnly(false);
// 生成请求
QueryRequest request = requestBuilder.build();
TagHostTable tabHostTable = new TagHostTable(tagDataTableName, connection);
try {
// 执行查询
QueryResult result = tabHostTable.query(request);
// 返回第一页的前10条结果
List<byte[]> tagHosts = result.listTagHosts(tabHostTable, 0, 10);
for (byte[] tagHost : tagHosts) {
System.out.println(Bytes.toString(tagHost));
}
} catch (IOException e) {
e.printStackTrace();
}
}
使用上面的标签搜索,可以自由组合各个标签条件来搜索,而且响应为秒级别,基本性能能满足要求。
- 点赞
- 收藏
- 关注作者
评论(0)