HBase 之五 Coprocessor 协处理器及实现案例

本文介绍了HBase的Coprocessor协处理器,包括Observer和Endpoint的分类和工作原理。通过一个RegionObserver的二级索引实现案例,详细讲解如何利用Coprocessor维护二级索引,提高查询效率。文章最后提到了动态加载Coprocessor的方法并验证了其实效。
摘要由CSDN通过智能技术生成

背景

​ HBase 在作为大数据生态中的 Nosql 数据库有用非常多的优点,但是其也存在一定的缺陷例如无法简单的维护二级索引(本文会介绍及实现),求和、排序、计数等简单操作需要通过 Client 走速度较慢的 MapReduce,为了解决这些问题 HBase 提供了 Coprocessor 协处理器来让用户可以在 server 端运行自己的代码,从而可以在让用户轻松的维护二级索引,在server 端实现聚合操作等。本文基于 1.3.1 版本Hbase。

协处理器分类

Observer

​ 这类协处理器类似于 RDBMS 中的 触发器(trigger),可以监测被观察对象的状态,当一些特定事件发生时被执行,这些事件包括 Client 发出的请求如 put,get 和 server 自动发生的事件,Hbase 当前提供了四种 Observer:

  • RegionObserver: 提供了 Client 相关操作如 put,get,delete 等的事件钩子
  • WALObserver:提供 WAL(预写日志write ahead log)相关操作钩子
  • MasterObserver:提供了 Client DLL 操作如 create,drop等的事件钩子
  • RegionServerObserver:提供了 HRegionServer 级别操作如 merger,rollback 等的事件钩子

​ 利用 Observer 用户可以使得 Hbase 在用户正常的 Client 端操作行为之上自动的执行一些额外的行为,下面用一张 RegionObserver 的流程图来说明一下工作机制(图源来自网络):

在这里插入图片描述

  1. Client 发起 get 请求
  2. 根据 meta data 该请求被发向合适的 HRegionServer 和 Region
  3. coprocessorHost 拦截该请求,并遍历等登记在该表的上所有 RegionObserver 并调用 preGet()
  4. get 请求发送到 Region 并执行相应操作
  5. get 请求的返回值再次被 coprocessorHost 拦截,并遍历调用 postGet() 操作
  6. get 结果返回给客户端

可以看到就 RegionObserver 而言我们可以在一次数据操作如 get 中插入俩个执行时机:1)region 得到请求前;2)region 执行完请求后

Endpoint

​ 这类协处理器类似于存储过程,Endpoint 是动态 RPC 插件的接口,其具体实现被安装在服务器端,用户可以通过 HBase API 远程调用,并在服务器端的目标 region 中完成计算而后将结果返回给 Client,EndPoint 的调用过程如下图(图源来自网络):在这里插入图片描述

在 1.x Hbase 版本后 endpoint 的 API 有很大的变化新的 endpoint 使用步骤如下:

  1. 编写一个 ProtocolBuffer 格式的 proto 文件,其中需要定义 service 和 message
  2. 将 proto 文件编译成 java 代码
  3. 编写 endpoint 类,该类需要实现 proto 文件生成的 Service 接口以及 CoprocessorService 接口,并且 CoprocessorService.getService() 方法需要返回 Service 实例

RegionObserver 实现二级索引案例

​ 讲完了俩种协处理器,我们来自己实现一个小案例加深一下印象,前文有说到 Hbase 本身没有索引机制,而我们可以用二级索引的方法来模拟索引来加快查询的效率,使用协处理器能帮我们自动的维护二级索引。

什么是二级索引

​ 说了那么多二级索引,那到底啥是二级索引呢?说起来也不难直接举个栗子,现在我们有一张 student 表表结构和数据如下:

student:
rowKey    columnFamily
id        info

1001      info:name = zhangsan, info:age = 23
1002      info:name = lisi, info:age = 24
1003      info:name = zhangsan, info:ane = 29

​ 现在我们想在 name 列上加索引以达到能快速查询某个人年龄统计值的目的,那么我们可以创建一张索引表,表中的 rowKey 为具体的姓名,而 value 为 student 表中对应的 rowKey,具体的表结构如下:

student_index
rowKey     columnFamily
name       student-id
zhangsan   info:1001 = 1001, info:1003 = 1003
lisi       info:1002 = 1002

​ 上面的 student_index 就是所说的二级索引,通过这种方式我们可以先查找 student_index 表来得到 name 为 zhangsan 的所有 rowKey,然后再用这些 rowKey 查询 student 从而加快查询效率。

Coprocessor 实现二级索引

​ OK,了解了什么是二级索引现在我们就用协处理器来自己简单的实现一个,我们的需求是这样:每次向 student 表中 put 一条含有 name 列的新记录,都会在 student_index 表中记录该 name 值对应的 rowKey。

  1. 实现一个我们自己的 coprocessor 类,因为是监控 region 的操作因此需要继承 BaseRegionObserver

    public class StudentIndexCoprocessor extends BaseRegionObserver {
         
        // 这里我们实现 postPut 方法在 student 表 put 完成后再在 student_index 表插入数据
        @Override
        public void postPut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException {
         
            // 获取目标 index 表
            TableName tableName = TableName.valueOf("anvna:student_index");
            Table table =
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值