一篇文章搞懂 HBase 的 Coprocessor

前言

本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见大数据技术体系


Coprocessor

HBase 使用 Coprocessor 机制,使用户可以将自己编写的程序运行在 RegionServer上。

大多数情况下 HBase 用户并不需要这个功能,通过调用 HBase 提供的读写 API 或者使用 Bulkload 功能基本上可以满足日常的业务需求。

但在部分特殊应用场景下,使用 Coprocessor 可以大幅提升业务的执行效率。

比如,业务需要从 HBase 集群加载出来几十亿行数据进行求和运算或是求平均值运算,如果调用 HBase API 将数据全部扫描出来在客户端进行计算,势必有下列问题:

  • 大量数据传输可能会成为瓶颈,这就导致整个业务的执行效率可能受限于数据的传输效率。
  • 客户端内存可能会因为无法存储如此大量的数据而 OOM 。
  • 大量数据传输可能将集群带宽耗尽,严重影响集群中其他业务的正常读写。

这种场景下,如果能够将客户端的计算代码迁移到 RegionServer 服务器端执行,就能很好地避免上述问题,在保证不影响其他业务的情况下提升计算效率。


Coprocessor 分类

HBaseCoprocessor 分为两种: Observer 和 Endpoint ,如下图所示。

在这里插入图片描述

Observer Coprocessor 类似于 MySQL 中的触发器。

Observer Coprocessor 提供钩子使用户代码在特定事件发生之前或者之后得到执行。

比如,想在调用 get 方法之前执行你的代码逻辑,可以重写如下方法:

    public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results) throws IOException

同理,如果想在调用 get 方法之后执行你的代码逻辑,可以重写 postGet 方法:

    public void postGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results) throws IOException

下图以 preGet 和 postGet 为例说明 ObserverCoprocessor 与 RegionServer 中其他组件的协作关系。

在这里插入图片描述

使用 Observer Coprocessor 的最典型案例是在执行 put 或者 get 等操作之前检查用户权限。

在当前 HBase 系统中,提供了 4 种 Observer 接口:

  • RegionObserver,主要监听 Region 相关事件,比如 get 、 put 、 scan 、 delete 以及 flush 等。
  • RegionServerObserver ,主要监听 RegionServer 相关事件,比如 RegionServer 启动、关闭,或者执行 Region 合并等事件。
  • WALObserver ,主要监听 WAL 相关事件,比如 WAL 写入、滚动等。
  • MasterObserver ,主要监听 Master 相关事件,比如建表、删表以及修改表结构等。

EndpointCoprocessor 类似于 MySQL 中的存储过程。

EndpointCoprocessor 允许将用户代码下推到数据层执行。

一个典型的例子就是计算一张表(设计大量 Region ) 的平均值或者求和,可以使用 EndpointCoprocessor 将计算逻辑下推到 RegionServer 执行。

通过 EndpointCoprocessor ,用户可以自定义一个客户端与 RegionServer 通信的 RPC 调用协议,通过 RPC 调用执行部署在服务器端的业务代码。

需要注意的是, ObserverCoprocessor 执行对用户来说是透明的,只要 HBase 系统执行了 get 操作,对应的 preGetOp 就会得到执行,不需要用户显式调用 preGetOp 方法;而 EndpointCoprocessor 执行必须由用户显式触发调用。


Coprocessor 加载

用户定义的 Coprocessor 可以通过两种方式加载到 RegionServer ;一种是通过配置文件静态加载;一种是动态加载。


1 .静态加载

通过静态加载的方式将 Coprocessor 加载到集群需要执行以下 3 个步骤。

  1. 将 Coprocessor 配置到 hbase-site.xml。 hbase-site.xml 中定义了多个相关的配置项:
配置Observer
hbase.coprocessor.region.classesRegionObservers 和 EndpointCoprocessor
hbase.coprocessor.wal.classesWALObservers
hbase.coprocessor.master.classeMasterObservers

比如业务实现一个 EndpointCoprocessor ,需要按如下方式配置到 hbase-site.xml:

<property> 
<name>hbase.coprocessor.region.classes</name> 
<value>com.shockang.study.hbase.coprocessor.endpoint.SumEndPoint</value> 
</property>
  1. 将 Coprocessor 代码放到 HBase 的 classpath 下。最简单的方法是将 Coprocessor 对应的 jar 包放在 HBase lib 目录下。
  2. 重启 HBase 集群。

2. 动态加载

静态加载 Coprocessor 需要重启集群,使用动态加载方式则不需要重启。 动态加载当前主要有 3 种方式。


方式 1:使用 shell

  1. disable 表,代码如下:
hbase(main):001:0> disable 'users'
  1. 修改表 schema ,代码如下:
hbase(main):002:0> alter 'users', METHOD =>'table_att','Coprocessor'=>'hdfs://.../coprocessor.jar| com.shockang.study.hbase.Coprocessor.RegionobserverExample "/"

其中, hdfs://.../coprocessor.jar 表示 Coprocessor 代码部署在 HDFS 的具体路径, com.shockang.study.hbase.Coprocessor.RegionobserverExample
是执行类的全称。

  1. enable 表,代码如下:
hbase(main):003:0> enable 'users'

方式2:使用HTableDescriptor 的 setValue() 方法

代码如下:

String path="hdfs://.../coprocessor.jar"; 
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
hTableDescriptor.setvalue("COPROCESSORS1",path + "/" RegionObserverExample.class.getCanonicalName()+"/" Coprocessor.PRIORITY_USER);

方式3:使用 HTableDescriptor 的 addCoprocessor() 方法

代码如下:

Path path = new Path("hdfs://coprocessor_path");
TableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
hTableDescriptor.addCoprocessor(RegionobserverExample.class.getCanonicalName(), path, Coprocessor.PRIORITY_USER, null);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值