HBase 解析 | HBase二级索引方案解析
共 366字,需浏览 1分钟
·
2021-11-08 17:44
什么是二级索引
HBase中的一级索引
指数据在写入region
时,会根据rowkey
进行排序后写入,之后regionserver
在加载region
时,会自动为当前region
的rowkey
创建一个LSM树的索引,方便对当前region
,rowkey
的查询。
那么问题来了。HBase本身只提供基于行键和全表扫描的查询,而行键索引单一,对于多维度的查询困难。
二级索引的本质就是建立各列值与行键之间的映射关系
。
Coprocessor
在讲解如何构建二级索引前,我们有必要简单介绍一下Coprocessor
这个核心特性。
在旧版本的(<0.92)Hbase中,统计数据表的总行数,需要使用Counter
方法,执行一次MapReduce Job
才能得到。虽然HBase在数据存储层中集成了MapReduce
,能够有效用于数据表的分布式计算。然而在很多情况下,做一些简单的相加或者聚合计算的时候,如果直接将计算过程放置在server 端,能够减少通讯开销,从而获得很好的性能提升。
在这种情况下,协处理器(Coprocessor)应运而生。它允许你将业务计算代码放入在RegionServer
的协处理器中,将处理好的数据再返回给客户端,这可以极大地降低需要传输的数据量,从而获得性能上的提升。同时协处理器也允许用户扩展实现HBase
目前所不具备的功能,如权限校验、二级索引、完整性约束等。
于是,HBase在0.92版本之后引入了协处理器(coprocessors),实现了一些激动人心的新特性:能够轻易建立二次索引、复杂过滤器(谓词下推)以及访问控制等。
协处理器类型
Observer协处理器
类似于传统数据库中的触发器,当发生某些事件的时候这类协处理器会被 Server 端调用。
Observer Coprocessor
就是一些散布在 HBase Server 端代码中的 hook 钩子,在固定的事件发生时被调用。比如:put 操作之前有钩子函数prePut
,该函数在 put 操作执行前会被Region Server
调用;在 put 操作之后则有postPut
`钩子函数。
当前Observer协处理器有下面4种类型:
RegionObserver:允许您观察 Region 上的事件,例如 Get 和 Put 操作; RegionServerObserver:允许您观察与 RegionServer 操作相关的事件,例如启动、停止或执行合并、提交或回滚。 WALObserver:提供 WAL 相关操作钩子; MasterObserver:提供 DDL-类型的操作钩子。如创建、删除、修改数据表等。
以上四种类型的 Observer 协处理器均继承自Coprocessor
接口;这四个接口中分别定义了所有可用的钩子方法以便在对应方法前后执行特定的操作。通常情况下我们并不会直接实现上面接口而是继承其Base实现类,Base 实现类只是简单空实现了接口中的方法,这样我们在实现自定义的协处理器时就不必实现所有方法只需要重写必要方法即可。
下面是以RegionObserver
为例子讲解Observer
这种协处理器的原理:
客户端发起get请求 该请求被分派给合适的 RegionServer
和RegioncoprocessorHost
拦截该请求,然后在该表上登记的每个RegionObserer
上调用preGet()如果没有被preGet拦截,该请求继续送到Region,然后进行处理 Region产生的结果再次被 coprocessorHost
拦截,调用postGet()处理假如没有postGet()拦截该响应,最终结果被返回给客户端
Observer协处理器
Endpoint
协处理器类似传统数据库中的存储过程,客户端可以调用这些 Endpoint
协处理器执行一段Server
端代码,并将Server
端代码的结果返回给客户端进一步处理,最常见的用法就是进行聚集操作;
如果没有协处理器,当用户需要找出一张表中的最大数据,即max 聚合操作,就必须进行全表扫描,在客户端代码内遍历扫描结果,并执行求最大值的操作。这样的方法无法利用底层集群的并发能力,而将所有计算都集中到 Client 端统一执 行,势必效率低下。
利用Coprocessor
,用户可以将求最大值的代码部署到HBase Server
端,HBase 将利用底层cluster
的多个节点并发执行求最大值的操作。即在每个 Region 范围内 执行求最大值的代码,将每个Region
的最大值在Region Server
端计算出,仅仅将该 max 值返回给客户端。在客户端进一步将多个Region
的最大值进一步处理而找到其中的最大值。这样整体的执行效率就会提高很多。
总体来看
Observer
允许集群在正常的客户端操作过程中可以有不同的行为表现Endpoint
允许扩展集群的能力,对客户端应用开放新的运算命令Observer
类似于 RDBMS 中的触发器,主要在服务端工作Endpoint
类似于 RDBMS 中的存储过程,主要在服务端工作Observer
可以实现权限管理、优先级设置、监控、ddl 控制、二级索引等功能Endpoint
可以实现 min、max、avg、sum、distinct、group by 等功能
基于上面的基本知识,Hbase二级索引的实现主要分为2种:
Coprocessor方案
和非Coprocessor方案
。
Coprocessor方案(Phoenix等)
其实从0.94版本开始,HBase官方文档已经提出了hbase上面实现二级索引的一种路径:
基于Coprocessor
(0.92版本开始引入,达到支持类似传统RDBMS的触发器的行为)开发自定义数据处理逻辑,采用数据"双写"(dual-write)策略,在有数据写入同时同步到二级索引表。
虽然官方一直也没提供内置的支持二级索引的工具, 不过业界也有些比较知名的基于Coprocessor
的开源方案:
华为的hindex
: 基于0.94版本,当年刚出来的时候比较火,但是版本较旧,看GitHub项目地址最近这几年就没更新过。
Apache Phoenix
: 功能围绕着SQL on hbase,支持和兼容多个hbase版本, 二级索引只是其中一块功能。二级索引的创建和管理直接有SQL语法支持,使用起来很简便, 该项目目前社区活跃度和版本更新迭代情况都比较好。
Apache Phoenix
在目前开源的方案中,是一个比较优的选择。主打SQL on HBase
, 基于SQL能完成HBase的CRUD操作,支持JDBC协议。Apache Phoenix
在Hadoop生态里面位置:
Phoenix二级索引特点
Covered Indexes
(覆盖索引) :把关注的数据字段也附在索引表上,只需要通过索引表就能返回所要查询的数据(列),所以索引的列必须包含所需查询的列(SELECT的列和WHRER的列)。Functional indexes
(函数索引):索引不局限于列,支持任意的表达式来创建索引。Global indexes
(全局索引):适用于读多写少场景。通过维护全局索引表,所有的更新和写操作都会引起索引的更新,写入性能受到影响。在读数据时,Phoenix SQL会基于索引字段,执行快速查询。Local indexes
(本地索引):适用于写多读少场景。在数据写入时,索引数据和表数据都会存储在本地。在数据读取时,由于无法预先确定region的位置,所以在读取数据时需要检查每个region(以找到索引数据),会带来一定性能(网络)开销。
优点: 基于Coprocessor的方案,从开发设计的角度看,把很多对二级索引管理的细节都封装在的Coprocessor具体实现类里面,这些细节对外面读写的人是无感知的, 简化了数据访问者的使用。
缺点: 但是Coprocessor的方案入侵性比较强, 增加了在Regionserver内部需要运行和维护二级索引关系表的代码逻辑等, 对Regionserver的性能会有一定影响。
非Coprocessor方案
选择不基于Coprocessor开发,自行在外部构建和维护索引关系也是另外一种方式。
常见的是采用底层基于Apache Lucene的Elasticsearch(下面简称ES)或Apache Solr ,来构建强大的索引能力、搜索能力, 例如支持模糊查询、全文检索、组合查询、排序等。
Lily HBase Indexer
Lily HBase Indexer
(也简称 HBase Indexer)是国外的NGDATA公司开源的基于solr的索引构建工具,特色是其基于HBase的备份机制,开发了一个叫SEP工具,通过监控HBase 的WAL日志(Put/Delete操作),来触发对solr集群索引的异步更新,基本对HBase无侵入性(但必须开启WAL)流程图如下所示:
CDH Search
CDHSearch
是Hadoop发行商Cloudera公司开发的基于solr的HBase检索方案,部分集成了Lily HBase Indexer
的功能。
下面是CDH search的核心组件交互图, 体现了在单次client端查询过程中, 核心的zookeeper和solr等的交互流程:
例如, Hbase结合Solr的场景:
基于Solr的HBase多条件查询原理很简单,将HBase表中涉及条件过滤的字段和rowkey在Solr中建立索引,通过Solr的多条件查询快速获得符合过滤条件的rowkey值,拿到这些rowkey之后在HBASE中通过指定rowkey进行查询。
其他方案
对于在外部自定义构建二级索引的方式,有自己的大数据团队的公司一般都会针对自己的业务场景进行优化,自行构建ES/Solr的搜索集群。例如基于ES构建海量索引和检索能力的案例: