观察者(Observer)
观察者的设计意图是允许用户通过插入代码来重载协处理器框架的upcall方法,而具体的事件触发的callback方法由HBase的核心代码来执行。协处理器框架处理所有的callback调用细节,协处理器自身只需要插入添加或者改变的功能。
以HBase0.92版本为例,它提供了三种观察者接口:
- RegionObserver:提供客户端的数据操纵事件钩子:Get、Put、Delete、Scan等。
- WALObserver:提供WAL相关操作钩子。
- MasterObserver:提供DDL-类型的操作钩子。如创建、删除、修改数据表等。
这些接口可以同时使用在同一个地方,按照不同优先级顺序执行.用户可以任意基于协处理器实现复杂的HBase功能层。HBase有很多种事件可以触发观察者方法,这些事件与方法从HBase0.92版本起,都会集成在HBase API中。不过这些API可能会由于各种原因有所改动,不同版本的接口改动比较大,具体参考Java Doc。
RegionObserver工作原理,如图1所示。更多关于Observer细节请参见HBaseBook的第9.6.3章节。
图 RegionObserver工作原理
启用协处理器 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
(3)重启指定表
实例代码(往一张表里插入数据时,向另一张表写数据):
package cproc.datacube.client.test;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
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 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 kv = put.get("familyName".getBytes(),
"columnName".getBytes());
Iterator 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();
}
}