一种HBase上Region级别的二级索引存储
转载自:http://zjushch.iteye.com/blog/1910218
我们会经常谈及二级索引,这是对全表数据进行另外一种方式的组织存储,是针对table级别的。如果要为HBase上的表实现一个强一致性的二级索引,那么就无法逃避分布式事务,而这一直是用户最期待的功能。 而即使只需要保证最终一致性,这个索引也并不好实现,因为你需要额外的表以存储过程数据,需要解决宕机恢复问题等
撇开分布式事务,我们是否可以考虑对索引的要求进行降级,比如把Region看成是全表下的子表,实现一套Region级别的索引,通过功能上的牺牲以换取实现的简易及稳定。
在某些存在用户概念的场景下,比如消费记录,我们总是会在确定的用户下,进行数据查找。这意味着,在此类场景中,我们只需要一个用户级别的索引。
举个例子,对于一笔交易记录,我们至少会有这么几个维度:
用户Id,交易时间,交易金额,交易状态(还会有交易名称,交易号ID,对方ID等)
当存储于HBase时,一般可以这么组织:
RowKey= 用户Id+交易时间
列1=交易金额
列2=交易状态
所以当我们要读取某个用户的在某段时间内的交易记录的时候,我们可以设置一个Scan:
startRow=用户Id+开始时间
stopRow=用户Id+结束时间
如果我们要增加查找条件,进行过滤,比如要读取某个用户在某段时间内交易状态为取消的交易记录,我们可以为上述Scan设置一个Filter,来过滤不符合查询条件的结果。
如果这是一个大商户,某段时间内的交易记录数巨多,通过设置Filter来过滤的方式就显得效率低下,开销巨大。
为了优化此类查找,业务只能自建索引表,可以如下组织:
RowKey= 用户Id+交易状态+交易时间
列1=交易金额
由此产生的问题时,当产生一笔交易记录的时候,我们需要向2张表中写入数据,不用说原子性,为了保证最终一致性,也得会花费不少的力气
彼之痛,己之痛,或许一个Region级别的索引存储能有一定的疗效。
什么是Region级别的索引存储
我们知道在HBase的结构中,一个Region可以包含多个Store,而索引存储则也是Region下面的一个Store,我们称其为Assistant Store,但它会有一些不同点:
a.Assistant Store中的数据由Regionserver按照用户配置的规则自动写入,是源数据的一份拷贝,但是拥有不同的组织方式
b.Assistant Store中的数据可以不遵守Region的Row范围限制
c.Assistant Store中的数据由用户主动选择读取(不会智能的自动利用)
d.Assistant Store中的数据在Split时,遵守与源数据对应的原则
(可以先看例子)
一个简单的例子
假设现在表只有一个Region,往表写入以下6行数据:
r1/c1:q1/v1
r2/c1:q1/v2
r3/c1:q1/v1
r4/c1:q1/v2
r5/c1:q1/v1
r6/c1:q1/v2
如果我们已为这个表配置了一个简单的索引存储,该Assistant Store命名为c2,那么除了上面的数据,Region中还会包含以下数据:
v1/c2:q1/r1
v1/c2:q1/r3
v1/c2:q1/r5
v2/c2:q1/r2 (在插入源数据的时候自动生成,存在Assistant Store中)
v2/c2:q1/r4
v2/c2:q1/r6
显然,这些是简单的倒置索引数据(可以由用户定义生成的数据如何组织),当你对表进行正常的scan时候,你只能见到源数据,即r1,r2,...,r6。 但是你可以通过某种方式,访问Assistant Store中的数据,即v1,v2,以加快条件查找
Region分裂处理
如果我们将上面这个例子中的Region进行Split,Split row为'r4',那么源数据就会被分落在两个子Region中,Daughter_A 和 Daughter_B;
Daughter_A 包含如下源数据:
r1/c1:q1/v1
r2/c1:q1/v2
r3/c1:q1/v1
Daughter_B 包含如下源数据:
r4/c1:q1/v2
r5/c1:q1/v1
r6/c1:q1/v2
Assistant Store中的生成数据会遵守与源数据对应的原则,
Daughter_A 的Assistant Store中的索引数据为:
v1/c2:q1/r1
v1/c2:q1/r3
v2/c2:q1/r2
Daughter_B 的Assistant Store中的索引数据为:
v1/c2:q1/r5
v2/c2:q1/r4
v2/c2:q1/r6
原子性和一致性
解决了数据组织的问题,我们来看看如何保证源数据和生成数据间的原子性和一致性。
从上面的例子描述中,我们知道,设置了索引存储后,当我们写入一行数据时,实际上会存储多行数据,但这多行数据都是在同个Region中,这意味着可以用一个本地事务解决这多行数据的事务写入。或许有些用户不知道,HBase-0.94版本早就实现了本地Region的多行事务。
回看Region级别的索引存储的特点
a.Assistant Store中的数据由Regionserver按照用户配置的规则自动写入,是源数据的一份拷贝,但是拥有不同的组织方式
用户可以通过扩展类Assistant,来生成自己定义的数据格式,存储到Assistant Store中,
比如对于r1/c1:q1/v1,你可以生成一行v1/c1:q1/r1, 也可以生成一行v1r1/c1:q1/r1,也可以生成多行,但是生成的数据有一个限制,就是value值必须为源数据中的row值,这是为了保证源数据与生成数据之间能对应起来,当Region进行分裂的时候,索引数据和源数据仍然是对应的
b.Assistant Store中的数据可以不遵守Region的Row范围限制
从上面的例子中,我们可以看出,Assistant Store中的数据的Row是由用户自定义的,所以其Row是任意的,不会在Region的Row范围内
c.Assistant Store中的数据由用户主动选择读取(不会智能的自动利用)
Assistant Store中的数据的写入用系统自动控制,但是目前的设计中,读取由用户主动发起
d.Assistant Store中的数据在Split时,遵守与源数据对应的原则
优劣分析
优点:
1.设计简单,实现方便
2.加速条件Scan ,提高效率
3.相比于不设置索引存储,写入性能几乎不受影响,因为多行数据只会写一次Log
(无论是分布式事务,或者用户自己写入多张表,都无法避免写入多行数据时要多次写Log)
缺点:
1.额外存储空间
2.相比于全局意义上的二级索引,使用上会有局限性
重新思考上面的交易记录的案例
如果有了Region级别的索引存储,我们可以为交易记录表设置1个或多个Assistant Store,
源数据的组织仍然同上:
RowKey= 用户Id+交易时间
列1=交易金额
列2=交易状态
Assistant Store中的数据组织为:
RowKey= 用户Id+交易状态+交易时间
列1=交易金额
虽然结构上和用户写多张表一样,但是不需要为解决原子性和一致性而烦恼。
当然细心的读者,会发现从Assistant Store中扫描出来的数据无法做到ordered by 源数据中的Row,要做到ordered by Assistant Store中的Row也得花一定的力气。
怎么使用索引存储?
功能的基本代码已开发完,可以见https://issues.apache.org/jira/browse/HBASE-8980
如何让目前的HBase用户平滑使用,也是一个不小的难题,主要是有这么几点。
1.API使用
按照目前的设计,用户需要通过Scan方式主动的去读取索引存储,示例
01
|
//从源数据的Row上 限制扫描范围
|
02
|
Scan scan = new Scan();
|
03
|
scan.setStartRow( 'r1' );
|
04
|
scan.setStopRow( 'r7' );
|
05
|
06
|
//创建在Assistant Store运行的Scan,从v2 到 v2+
|
07
|
Scan assistantScan = new Scan().setStartRow( 'v2' ).setStopRow( 'v2' + '(byte)0x00' );
|
08
|
//设置这个以后,Region在解析的时候,会在Assistant Store上运行这个Scan
|
09
|
scan.setAssistantScan(assistantScan);
|
10
|
11
|
scanner = htable.getScanner(scan);
|
12
|
for (Result result:scanner){
|
13
|
//输出
|
14
|
v2/c2:q1/r2
|
15
|
v2/c2:q1/r4
|
16
|
v2/c2:q1/r6
|
17
|
}
|
2.Ordered by特性保证
目前实现中没有,准备后续再添加
3.已有数据的索引追加
目前实现中没有,准备后续再添加
一种HBase上Region级别的二级索引存储相关推荐
- HBase优化之Apache Phoenix二级索引
索引分类 全局索引 本地索引 覆盖索引 函数索引 全局索引 全局索引适用于读多写少业务 当构建了全局索引时,Phoenix会拦截写入(DELETE.UPSERT值和UPSERT SELECT)上的数据 ...
- java分词器和索引器_solr-hbase二级索引及查询解决方案(一)
solr-hbase二级索引及查询解决方案(一) 发布时间:2018-02-28 21:41, 浏览次数:636 , 标签: solr hbase 最近要搞一个查询功能,是把hbase中的数据方便的查 ...
- MySQL聚簇索引和二级索引的区别
主键索引的叶子节点存的是整行数据.在InnoDB里,主键索引也被称为聚簇索引(clustered index). 非主键索引的叶子节点内容是主键的值.在InnoDB里,非主键索引也被称为二级索引(se ...
- 《MySQL是怎样运行的:从根儿上理解MySQL》- mysql 数据存储
<MySQL是怎样运行的:从根儿上理解MySQL>- mysql 数据存储 <MySQL是怎样运行的:从根儿上理解MySQL>读书笔记 InnoDb数据页结构 页是 InnoD ...
- (转)HBase二级索引与Join
二级索引与索引Join是Online业务系统要求存储引擎提供的基本特性.RDBMS支持得比较好,NOSQL阵营也在摸索着符合自身特点的最佳解决方案. 这篇文章会以HBase做为对象来探讨如何基于Hba ...
- HBase phoenix二级索引
1. 为什么需要用二级索引? 对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询.如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄.对于较大的表 ...
- api 原生hbase_数据查询的玄铁剑:云HBase原生二级索引发布
HBase原生提供了主键索引,用户可以根据Rowkey进行高效的单行读.前缀匹配.范围查询操作.但若需要使用属性列进行查询时,则只能使用filter在查询范围内进行逐行过滤.在扫描范围较大时,会浪费大 ...
- HBase二级索引的设计与应用(详解)
最近面试,涉及到了HBase的多条件组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowKe ...
- HBase建表高级属性,hbase应用案例看行键设计,HBase和mapreduce结合,从Hbase中读取数据、分析,写入hdfs,从hdfs中读取数据写入Hbase,协处理器和二级索引
1. Hbase高级应用 1.1建表高级属性 下面几个shell 命令在hbase操作中可以起到很到的作用,且主要体现在建表的过程中,看下面几个create 属性 1. BLOOMFILTER 默认是 ...
最新文章
- Cell:康奈尔大学郭春君组开发针对非模式肠道细菌的基因编辑工具
- JAVA项目怎么不是蓝色_解决IDEA创建maven项目时pom.xml没有变蓝的问题
- TPC-C中跑赢Oracle的OceanBase,最近有何惊艳?
- EIM正在迎来自己的春天
- 20 FI配置-财务会计-定义税务科目
- hive币2021年预计涨到多少_星时代云播|IPFS/Filecoin的价值被严重低估, FIL能不能涨到300美金?...
- TensorFlow: 薛定谔的管道
- AI 智能会议系统(36)——-外呼失败场景如何处理?
- [PyTorch] PyTorch版本不兼容问题+更新日志链接
- ubuntu-常用命令汇总
- C++学习总结(1)
- VMware vCloud Director视频教程
- 保存网页图片的八种方法
- 基金定投如何选择买卖点?——关于定投的择时研究
- 计算机sci多少字,一篇英文sci论文多少字
- HDU 5956 The Elder(斜率优化DP)
- iOS 图片自由裁剪
- SDUST 第四次作业
- [CSP-S模拟测试]:夜鹰与玫瑰(数学)
- 名校高考模拟试卷(试题)汇总(陆续更新)
热门文章
- java quartz实例_Java任务调度框架Quartz教程实例
- got、plt表介绍
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Ubuntu12.04增加屏幕分辨率选项
- windows查看GPU信息(nvidia-smi)
- dreamweaver 正则表达式为属性值加上双引号_IT兄弟连 HTML5教程 HTML5表单 新增的表单属性3...
- centos linux mysql 5.5脚本全自动源码包 编译安装
- 微信小程序 地图功能的实现 map
- Nginx负载均衡的4种方式 :轮询-Round Robin 、Ip地址-ip_hash、最少连接-least_conn、加权-weight=n
- 计算机及应用学习顺序,自考计算机及应用专业经验谈