我们会经常谈及二级索引,这是对全表数据进行另外一种方式的组织存储,是针对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二级索引实现方案。基于hadoop平台,设计了Hbase的二级索引机制。
Lily HBase Indexer 使用 SolrCloud 来存储 HBase 的索引数据,当 HBase 执行写 入、更新或删除操作时,Indexer 通过 HBase 的 replication 功能来把这些操作抽象成一系 列的 Event 事件,并用来保证写入 Solr 中的 ...
该索引方案是一种较好的实现方式,而且是现有很少的hbase索引实现方法
楼主实操的步骤整理的,只需要将Zookeeper的ip换成自己集群的就可以一步步地跟着文档实现,感兴趣的同学可以看看。
public class IndexBuilder3 extends Configured{ public static class MapperIndex extends TableMapper,Put>{ private String tableName; private String columnFamily;...// 该列对应的索引表名字
奇虎360 HBASE 二级索引的设计与实践 pdf 完整版
奇虎360 HBASE 二级索引的设计与实践 pdf 完整版,支持千亿级数据量
本方案主要参照了华为公布的HBase二级索引实现方案。为每个DataTable创建一个与之对应的IndexTable,通过各种途径,保证IndexTable Region与DataTable Region一一对应,并且存储在同一个RegionServer上。
hbase+Coprocesser+solr实现二级索引,hbase13.1+solr-5.4.1
该文档主要用于创建在solr中创建hbase的二级索引的教程,新建solr的分片,以及后续修改和新建配置文件等,仅供参考
HBASE二级索引的设计与实践.ppt
HBase的region split策略一共有以下几种: 1、ConstantSizeRegionSplitPolicy 0.94版本前默认切分策略 当region大小大于某个阈值(hbase.hregion.max.filesize=10G)之后就会触发切分,一个region等分为2个region。 ...
淘宝选择HBASE的原因及应用举例,适合初学者
一、解决的问题 1、RowKey 例子 ...二、对于上面需求 简单解决方案(二级索引 相当于添加一层映射关系到 原RowKey) 增加新的Hbase表 RowKey:hive_table__date___date__hive_table (解释:hive_tabl
基于Solr的HBase多条件查询原理很简单,将HBase表中涉及条件过滤的字段和rowkey在Solr中建立索引,通过Solr的多条件查询快速获得符合过滤条件的rowkey值,拿到这些rowkey之后在HBASE中通过指定rowkey进行查询。
hbase-region-inspector, HBase区域统计信息的可视化仪表板 hbase-region-inspectorHBase区域统计信息的可视化仪表板。 用法下载与HBase集群版本匹配的可执行二进制插件,添加execute权限,并使用以下命令行参数启动...
基于索引列聚集的HBase二级索引设计,张祎,双锴,HBase作为Apache开源的列式存储数据库,在一定程度上解决了海量数据存储的问题,并提供了高效的数据读写性能。但是由于HBase缺乏二级��
基于协处理器的HBase分类二级索引设计.pdf
基于协处理器的HBase二级索引方法.pdf