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,获取所有实际数据。
成都加米谷大数据科技有限公司是一家专注于大数据人才培养的机构。由来自阿里、华为、京东、星环等国内知名企业的多位技术大牛联合创办,技术底蕴丰厚,勤奋创新,精通主流前沿大数据及人工智能相关技术。
以国家规划大数据产业发展战略为指引,以全国大数据技术和大数据分析人才的培养为使命,以提升就业能力、强化职业技术为目标。面向社会提供大数据、人工智能等前沿技术的培训业务。
以上所述就是小编给大家介绍的《HBase 二级索引实现方案》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MySQL——索引实现原理
- 基于 B + Tree 的索引实现
- Lucene倒排索引实现原理探秘(2)
- Sphinx&coreseek实现中文分词索引
- 使用 Docker 和 Nginx 实现简单目录索引服务
- 面试官:聊一下你对MySQL索引实现原理?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。