转载自: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级别的二级索引存储相关推荐

  1. HBase优化之Apache Phoenix二级索引

    索引分类 全局索引 本地索引 覆盖索引 函数索引 全局索引 全局索引适用于读多写少业务 当构建了全局索引时,Phoenix会拦截写入(DELETE.UPSERT值和UPSERT SELECT)上的数据 ...

  2. java分词器和索引器_solr-hbase二级索引及查询解决方案(一)

    solr-hbase二级索引及查询解决方案(一) 发布时间:2018-02-28 21:41, 浏览次数:636 , 标签: solr hbase 最近要搞一个查询功能,是把hbase中的数据方便的查 ...

  3. MySQL聚簇索引和二级索引的区别

    主键索引的叶子节点存的是整行数据.在InnoDB里,主键索引也被称为聚簇索引(clustered index). 非主键索引的叶子节点内容是主键的值.在InnoDB里,非主键索引也被称为二级索引(se ...

  4. 《MySQL是怎样运行的:从根儿上理解MySQL》- mysql 数据存储

    <MySQL是怎样运行的:从根儿上理解MySQL>- mysql 数据存储 <MySQL是怎样运行的:从根儿上理解MySQL>读书笔记 InnoDb数据页结构 页是 InnoD ...

  5. (转)HBase二级索引与Join

    二级索引与索引Join是Online业务系统要求存储引擎提供的基本特性.RDBMS支持得比较好,NOSQL阵营也在摸索着符合自身特点的最佳解决方案. 这篇文章会以HBase做为对象来探讨如何基于Hba ...

  6. HBase phoenix二级索引

    1. 为什么需要用二级索引? 对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询.如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄.对于较大的表 ...

  7. api 原生hbase_数据查询的玄铁剑:云HBase原生二级索引发布

    HBase原生提供了主键索引,用户可以根据Rowkey进行高效的单行读.前缀匹配.范围查询操作.但若需要使用属性列进行查询时,则只能使用filter在查询范围内进行逐行过滤.在扫描范围较大时,会浪费大 ...

  8. HBase二级索引的设计与应用(详解)

    最近面试,涉及到了HBase的多条件组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowKe ...

  9. HBase建表高级属性,hbase应用案例看行键设计,HBase和mapreduce结合,从Hbase中读取数据、分析,写入hdfs,从hdfs中读取数据写入Hbase,协处理器和二级索引

    1. Hbase高级应用 1.1建表高级属性 下面几个shell 命令在hbase操作中可以起到很到的作用,且主要体现在建表的过程中,看下面几个create 属性 1. BLOOMFILTER 默认是 ...

最新文章

  1. Cell:康奈尔大学郭春君组开发针对非模式肠道细菌的基因编辑工具
  2. JAVA项目怎么不是蓝色_解决IDEA创建maven项目时pom.xml没有变蓝的问题
  3. TPC-C中跑赢Oracle的OceanBase,最近有何惊艳?
  4. EIM正在迎来自己的春天
  5. 20 FI配置-财务会计-定义税务科目
  6. hive币2021年预计涨到多少_星时代云播|IPFS/Filecoin的价值被严重低估, FIL能不能涨到300美金?...
  7. TensorFlow: 薛定谔的管道
  8. AI 智能会议系统(36)——-外呼失败场景如何处理?
  9. [PyTorch] PyTorch版本不兼容问题+更新日志链接
  10. ubuntu-常用命令汇总
  11. C++学习总结(1)
  12. VMware vCloud Director视频教程
  13. 保存网页图片的八种方法
  14. 基金定投如何选择买卖点?——关于定投的择时研究
  15. 计算机sci多少字,一篇英文sci论文多少字
  16. HDU 5956 The Elder(斜率优化DP)
  17. iOS 图片自由裁剪
  18. SDUST 第四次作业
  19. [CSP-S模拟测试]:夜鹰与玫瑰(数学)
  20. 名校高考模拟试卷(试题)汇总(陆续更新)

热门文章

  1. java quartz实例_Java任务调度框架Quartz教程实例
  2. got、plt表介绍
  3. Android BlueDroid(三):BlueDroid蓝牙开启过程enable
  4. Ubuntu12.04增加屏幕分辨率选项
  5. windows查看GPU信息(nvidia-smi)
  6. dreamweaver 正则表达式为属性值加上双引号_IT兄弟连 HTML5教程 HTML5表单 新增的表单属性3...
  7. centos linux mysql 5.5脚本全自动源码包 编译安装
  8. 微信小程序 地图功能的实现 map
  9. Nginx负载均衡的4种方式 :轮询-Round Robin 、Ip地址-ip_hash、最少连接-least_conn、加权-weight=n
  10. 计算机及应用学习顺序,自考计算机及应用专业经验谈