1.协处理器出现的背景:

HBase作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和、计数、排序等操作。比如,在旧版本的(<0.92)Hbase中,统计数据表的总行数,需要使用Counter方法,执行一次MapReduce Job才能得到。虽然HBase在数据存储层中集成了MapReduce,能够有效用于数据表的分布式计算。然而在很多情况下,做一些简单的相加或者聚合计算的时候,如果直接将计算过程放置在server端,能够减少通讯开销,从而获得很好的性能提升。于是,HBase在0.92之后引入了协处理器(coprocessors),实现一些激动人心的新特性:能够轻易建立二次索引、复杂过滤器(谓词下推)以及访问控制等。

2.协处理器分为两种:

第一种是Observers,它实际类似于触发器,其实就是观察者模式,主要在服务端工作,在代码中嵌入执行语句,有pre和post(前置和后置动作);

第二种是Endpoint,它类似与存储过程,主要在client端工作。

observer可以实现权限管理、优先级设置、监控、ddl控制、二级索引等功能;

而endpoint可以实现min、mas、avg、sum等功能,coprocessor可以动态加载。

Observer处理器如下:

RegionObserver:提供数据操作事件钩子;

WALObserver:提供WAL(write ahead log)相关操作事件钩子;

MasterObserver:提供DDL操作事件钩子。

新版本增加了RegionServerObserver和BaseRegionServerObserver的协处理器类。

Endpoint(终端)处理器如下:

终端是动态RPC插件的接口,它的实现代码被安装在服务器端,从而能够通过HBase RPC唤醒。客户端类库提供了非常方便的方法来调用这些动态接口,它们可以在任意时候调用一个终端,它们的实现代码会被目标region远程执行,结果会返回到终端。用户可以结合使用这些强大的插件接口,为HBase添加全新的特性。终端的使用,如下面所示:

定义一个新的protocol接口,必须继承CoprocessorProtocol.

实现终端接口,该实现会被导入region环境执行。

继承抽象类BaseEndpointCoprocessor,

在客户端,终端可以被两个新的HBase Client API调用 。

单个region:HTableInterface.coprocessorProxy(Class protocol, byte row) 。

rigons区域:HTableInterface.coprocessorExec (Class protocol, byte startKey, byte endKey, Batch.Call callable)。

3. 二级索引的Observer例子:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
 
public class TestCoprocessor extends BaseRegionObserver {
 
@Override
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
final Put put, final WALEdit edit, final boolean writeToWAL)
throws IOException {
//set configuration
Configuration conf = new Configuration();
//need conf.set...
 
HTable table = new HTable(conf, "indexTableName");
List<KeyValue> kv = put.get("familyName".getBytes(), "columnName".getBytes());
Iterator<KeyValue> kvItor = kv.iterator();
while (kvItor.hasNext()) {
KeyValue tmp = kvItor.next();
Put indexPut = new Put(tmp.getValue());
indexPut.add("familyName".getBytes(), "columnName".getBytes(), tmp.getRow());
table.put(indexPut);
}
table.close();
}
}

写完后要加载到table里面去,先把该文件打包成test.jar并上传到hdfs的/demo路径下,然后操作如下:

1. disable ‘testTable’

2. alter ‘testTable’, METHOD=>’table_att’,’coprocessor’=>’hdfs:///demo/test.jar|com.aixahc.testhbase.TestCoprocessor|1001′

3. enable ‘testTable’

然后往testTable里面插数据就会自动往indexTableName写数据了。

4.启用协处理器 Aggregation(Enable Coprocessor Aggregation)

我们有两个方法:

1.启动全局aggregation,能够操纵所有的表上的数据。通过修改hbase-site.xml这个文件来实现,只需要添加如下代码:

<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>

2.启用表aggregation,只对特定的表生效。通过HBase Shell 来实现。

 

(1)disable指定表。hbase> disable 'mytable'

(2)添加aggregation hbase> alter 'mytable', METHOD => 'table_att','coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.AggregateImplementation||'

(3)重启指定表 hbase> enable 'mytable'