技术分享 | HBase二级索引实现方案

1. 概要设计

主要思路:

为每个DataTable创建一个与之对应的IndexTable,通过各种途径,保证IndexTable Region与DataTable Region一一对应,并且存储在同一个RegionServer上,存储结构如图所示。最终要实现的效果是,每个IndexTable Region是对应的DataTable Region的局部索引,使用索引进行查询时,将对每个IndexTable Region进行检索,找出所有符合条件的DataTable RowKey,再根据DataTable RowKey到对应的DataTable Region中读取相应DataTable Row。

2. 详细设计

2.1. IndexTable的创建

IndexTable的创建主要出现在两个时机,

一是创建新DataTable时,系统根据索引定义,自动创建对应的IndexTable;

二是对已存在的DataTable,用户调用接口方法,动态创建索引。

IndexTable的创建过程如下:

第一步,:

获取DataTable的所有RegionInfo,得到所有DataTable Region的StartKey。

第二步:

结合索引定义和DataTable Region的StartKey信息,调用HBaseAdmin的createTable(final HTableDescriptor desc, byte [][] splitKeys)方法创建索引表。

通过以上两步便建立了IndexTable Region和DataTable Region的以StartKey为依据的一一对应关系。

2.2. IndexTable RowKey的设计

IndexTable的RowKey由四部分组成,按顺序依次是:DataTable Region StartKey、IndexName、IndexValue和DataTable RowKey,如图所示。

DataTable Region StartKey。将DataTable Region的StartKey作为IndexTable Region的RowKey的第一部分,主要基于两个方面的考虑。

一是使得IndexTable Region和对应的DataTable Region拥有相同的StartKey,这样便可将StartKey作为两个Region的关联依据;

二是当DataTable Region分裂时,可使用相同的SplitKey对IndexTable Region进行相应的分裂操作,并将新产生的DataTable Region和IndexTable Region建立关联关系。

IndexName。

在一张DataTable的基础上可以定义多个索引,如果为每个索引创建一个IndexTable,则在实际应用过程中,势必会产生大量的IndexTable,当DataTable Region分裂时,还需要对与之关联的所有IndexTable Region分别执行分裂操作,这将消耗大量的系统资源,并且不易维护。因此,我们考虑将一张DataTable的所有索引数据,存放到同一张IndexTable中,不同索引的数据以IndexName进行区分。

IndexValue。如果索引是单列索引,IndexValue就是DataTable Row的某个Column Value,如果索引是组合索引的话,则IndexValue就是DataTable Row的多个Column Value组合而成的。

DataTable RowKey。被用来定位DataTable Row,以获取最终的数据。

2.3. IndexTable Region的分配控制

IndexTable Region的分配控制过程,即是保证IndexTable Region与DataTable Region的一一对应,并且被分配到同一个RegionServer的过程。

自定义LoadBalancer,重写balanceCluster方法,主要增加对IndexTable Region的分配控制。以相同的StartKey作为IndexTable Region和DataTable Region的关联依据,将IndexTable Region和与其对应的DataTable Region分配到同一个RegionServer。自定义LoadBalancer对IndexTable Region的分配控制过程如图所示。

注意:

这里只增加对IndexTable Region分配的控制,并不对DataTable Region的分配进行干预,DataTable Region由HBase按照指定的负载均衡策略进行分配,使得对现有HBase运行环境的影响降到最小。

2.4. IndexTable Region的分裂过程

本文将以一个示例讲述IndexTable Region的分裂过程,假设当前有一个DataTable Region和对应的IndexTable Region,如图所示,绿色表格为DataTable Region,红色表格为IndexTable Region。

根据概要设计中的说明,假设SplitKey:03,经过一系列操作之后,原来的DataTable Region和IndexTable Region均分裂成两个新的Region,并且依然保存一一对应关系。最终效果如图所示。

IndexTable Region具体分步骤说明如下:

第一步:

确定SplitKey后,遍历IndexTable Region中所有的行,找出所有DataTable RowKey大于或等于SplitKey的Row,如图所示。

第二步:

删除第一步找到的所有DataTable RowKey大于或等于SplitKey的Row,并将RowKey的第一部分(DataTable Region StartKey)替换成SplitKey后,重新插入到IndexTable Region中,如图所示。

第三步:

以SplitKey,同时对DataTable Region和IndexTable Region进行分裂操作,如图所示。最终达到如图所示的效果。

2.5. 数据的写入过程

数据的写入过程,主要通过Coprocessor代理完成,保证更新DataTable Region数据的同时更新IndexTable Region中的数据。具体步骤如图所示。

2.6. 数据的读取过程

与数据的写入过程一样,数据的读取过程也是由Coprocessor代理完成。Coprocessor收到查询请求后,首先判断是否可以利用某个索引,提高本次查询效率。如果有可用的索引,则先从IndexTable Region中查出所有符合条件的RowKey,再根据RowKey,从DataTable Region中查找出实际的数据返回给客户端。具体步骤如图所示。

注意:

描述的IndexTable Region分配机制,保证了IndexTable Region和对应的DataTable Region处于同一个RegionServer上,这样便解决了在有大量符合查询条件的Row的情况下,通过RowKey从DataTable Region中获取实际数据的效率问题。

此外,考虑到从IndexTable中获取的RowKey列表也是有序的,所以在实现时,并不直接调用HBase提供的Get接口,去获取单个实际数据,而是在HFile Data Index的辅助下,通过遍历HFile,获取所有实际数据。

原文发布于微信公众号 - 加米谷大数据(DtinoneBD)

原文发表时间:2018-01-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏林德熙的博客

C# 获取 PC 序列号

在 C++ 需要使用 GetSystemFirmwareTable 的方法来获得 PC 的序列号,需要写的代码很多,但是在 C# 可以使用 WMI 来拿到序列号

2611
来自专栏LanceToBigData

HttpClient(二)HttpClient使用Ip代理与处理连接超时

前言   其实前面写的那一点点东西都是轻轻点水,其实HttpClient还有很多强大的功能:   (1)实现了所有 HTTP 的方法(GET,POST,PUT,...

4078
来自专栏圣杰的专栏

ABP入门系列(16)——通过webapi与系统进行交互

源码路径:Github-LearningMpaAbp 1. 引言 上一节我们讲解了如何创建微信公众号模块,这一节我们就继续跟进,来讲一讲公众号模块如何与系统...

1.6K6
来自专栏挖坑填坑

使用.net core ABP和Angular模板构建博客管理系统(创建后端服务)

1062
来自专栏dotnet & java

WCF 入门 (21)

其实不太了解为什么第21集才讲这个Binding,下面都是一些概念性的东西,不过作为一个入门视频,了解一下也无妨吧。

925
来自专栏程序员的SOD蜜

使用命名管道实现进程间通信

创建命名管道 命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的。相比TCP通信方式,效率更高,但比共享内存要低点。 命名管...

2725
来自专栏蘑菇先生的技术笔记

c#实现redis客户端(一)

2946
来自专栏Kubernetes

Kubernetes Node Co

Author: xidianwangtao@gmail.com NewNodeController入口 Controller Manager在启动时,会启...

4957
来自专栏码农阿宇

.Net Core使用Redis的一个入门简单Demo

本例子讲述一个在.Net core环境中对Redis数据库进行增删改查操作。 首先,要安装好Redis数据库,至于怎么安装,本文不再赘述,可以自行百度,有很...

2765
来自专栏hbbliyong

WCF 学习总结2 -- 配置WCF

前面一篇文章《WCF 学习总结1 -- 简单实例》一股脑儿展示了几种WCF部署方式,其中配置文件(App.config/Web.config)都是IDE自动生成...

3107

扫码关注云+社区

领取腾讯云代金券