Coprocessor是HBase 0.92.0引入的特性。使用Coprocessor。能够将一些计算逻辑下推到HBase节点,HBase由一个单纯的存储系统升级为分布式数据处理平台。

Coprocessor分为两种:Observer和Endpoint。

Observer能改动扩展已有的client操作功能。而Endpoint能引入新的client操作。

Observer

Observer的作用类似于数据库的触发器或者AOP中的advice。下图为Put操作添加Observer,当中1-2-4-6是一次正常的Put操作RPC调用过程,而3和5属于Observer,能够在Put操作之前和之后添加自己定义处理逻辑。

Observer包含三种,RegionObserver(针对数据訪问和更新操作,执行在Region上)/WALObserver(针对WAL日志事件,执行在RegionServer上下文)/MasterObserver(针对DDL操作,执行在Master节点)。

Endpoint

Endpoint的作用则类似于数据库存储过程。实现机制是通过扩展HBase RPC协议,给client暴露新的操作接口。

例如以下图,client负责发起调用和收集结果,服务端各节点负责并行计算。

实战

以上一章的follows表为例,通过Observer实现followedBy被关注表数据一致性维护。Endpoint实现关注人数量统计。

由于要实如今插入follows表时自己主动插入followedBy表。须要用到关注人/被关注人username信息,所以首先升级schema。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWRvbnR3YW50b2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

实现Observer

代码中有三处凝视值得注意:

  1. postPut方法在put操作之后被调用。
  2. 假设通过hbase-site.xml安装Observer。会应用到全局全部表,所以这里推断put操作的是否follows表。

  3. 这里有点bad smell。Observer执行在服务器端。为了共用代码,又调用client代码,仅为演示作用。

packageHBaseIA.TwitBase.coprocessors;
//…
publicclass FollowsObserver extends BaseRegionObserver {
private HTablePool pool = null;
@Override
public void start(CoprocessorEnvironment env)throws IOException {
pool = newHTablePool(env.getConfiguration(), Integer.MAX_VALUE);
}
@Override
public void stop(CoprocessorEnvironment env)throws IOException {
pool.close();
}
@Override
public void postPut(//1,在Put操作之后调用
finalObserverContext<RegionCoprocessorEnvironment> e,
final Put put,
final WALEdit edit,
final boolean writeToWAL) throws IOException {
byte[] table=e.getEnvironment().getRegion().getRegionInfo().getTableName();
if (!Bytes.equals(table,FOLLOWS_TABLE_NAME))
return; //2,推断表名
KeyValue kv =put.get(RELATION_FAM, FROM).get(0);
String from =Bytes.toString(kv.getValue());
kv = put.get(RELATION_FAM,TO).get(0);
String to =Bytes.toString(kv.getValue());
RelationsDAO relations = newRelationsDAO(pool);
relations.addFollowedBy(to,from);//3,插入followedBy表
}
}

Observer的安装能够通过改动hbase-site.xml或者使用tableschema改动语句完毕,前者须要重新启动HBase服务,后者仅仅须要又一次上下线相应表。

$ hbase shell
HBaseShell; enter 'help<RETURN>' for list of supported commands.
Type"exit<RETURN>" to leave the HBase Shell
Version0.92.0, r1231986, Mon Jan 16 13:16:35 UTC 2012
hbase(main):001:0>disable 'follows'
0 row(s) in 7.0560 seconds
hbase(main):002:0>alter 'follows', METHOD => 'table_att',
'coprocessor'=>'file:///Users/ndimiduk/repos/hbaseiatwitbase/
target/twitbase-1.0.0.jar
|HBaseIA.TwitBase.coprocessors.FollowsObserver|1001|'
Updatingall regions with the new schema...
1/1regions updated.
Done.
0 row(s) in 1.0770 seconds
hbase(main):003:0>enable 'follows'
0 row(s) in 2.0760 seconds

当中1001为优先级。当载入多个Observer时。依照优先级次序执行。

实现Endpoint

关注人数量统计能够通过clientScan实现,相比Endpoint方案。有两个待改进点:

  1. 传输全部关注人到client,不必要的网络I/O。

  2. 拿到全部关注人Result结果后。遍历实现计数是单线程的。

实现Endpoint包含三部分

定义PRC接口

publicinterface RelationCountProtocol extends CoprocessorProtocol {
public long followedByCount(String userId) throwsIOException;
}

服务端实现

和client不同,InternalScanner执行在特定Region上。返回的是原始的KeyValue对象。

packageHBaseIA.TwitBase.coprocessors;
//…
publicclass RelationCountImpl extends BaseEndpointCoprocessor implementsRelationCountProtocol {
@Override
public longfollowedByCount(String userId) throws IOException {
byte[]startkey = Md5Utils.md5sum(userId);
Scan scan = newScan(startkey);
scan.setFilter(newPrefixFilter(startkey));
scan.addColumn(RELATION_FAM,FROM);
scan.setMaxVersions(1);
RegionCoprocessorEnvironmentenv= (RegionCoprocessorEnvironment)getEnvironment();
InternalScanner scanner =env.getRegion().getScanner(scan);//1,server端
long sum = 0;
List<KeyValue> results= new ArrayList<KeyValue>();
boolean hasMore = false;
do {
hasMore =scanner.next(results);
sum += results.size();
results.clear();
} while (hasMore);
scanner.close();
return sum;
}
}

client代码

參考凝视:

  1. 定义Call实例
  2. 调用服务端Endpoint。
  3. 聚合全部RegionServer得到的结果
public long followedByCount (final String userId) throws Throwable {
HTableInterface followed =pool.getTable(FOLLOWED_TABLE_NAME);
final byte[] startKey = Md5Utils.md5sum(userId);
final byte[] endKey =Arrays.copyOf(startKey, startKey.length);
endKey[endKey.length-1]++;
Batch.Call<RelationCountProtocol,Long> callable =
newBatch.Call<RelationCountProtocol, Long>() {
@Override
public Longcall(RelationCountProtocol instance) throws IOException {
returninstance.followedByCount(userId);
}
};//1 call instance
Map<byte[], Long>results = followed.coprocessorExec(
RelationCountProtocol.class,
startKey,
endKey,
callable);//2 invoke endpoint
long sum = 0;
for(Map.Entry<byte[],Long> e : results.entrySet()) {
sum +=e.getValue().longValue();
}//3 aggreagte results
return sum;
}

Endpoint仅仅能通过配置文件部署,还须要将相关jar包增加到HBase classpath。

<property>
<name>hbase.coprocessor.region.classes</name>
<value>HBaseIA.TwitBase.coprocessors.RelationCountImpl</value>
</property>

读书笔记-HBase in Action-第二部分Advanced concepts-(2)Coprocessor的更多相关文章

  1. 读书笔记-HBase in Action-第二部分Advanced concepts-(1)HBase table design

    本章以山寨版Twitter为例介绍HBase Schema设计模式.广义的HBase Schema设计不仅仅包含创建表时指定项,还应该综合考虑Column families/Column qualif ...

  2. 读书笔记-HBase in Action-第二部分Advanced concepts-(3)非Javaclient

    HBase Shell HBase shell使用起来最方便,进入HBase shell控制台就可以使用. $ $HBASE_HOME/bin/hbase shell 常见操作有create(创建表) ...

  3. 读书笔记-HBase in Action-第一部分 HBase fundamentals

    新项目准备上HBase.HBase眼下由组里某牛负责.本着学会使用HBase的目标,先阅读下HBase in Action,一共十章组织成三部分,须要学习的内容包含HBase基本实现原理,用法,Sch ...

  4. unix 环境高级编程-读书笔记与习题解答-第二篇

    第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...

  5. 读书笔记-HBase in Action-第三部分应用-(1)OpenTSDB

    OpenTSDB是基于HBase的开源监控系统,能够支持上万规模集群监控和上亿数据点採集. 当中TSDB代表Time Series Database,OpenTSDB在时间序列数据的存储和查询上都做了 ...

  6. 读书笔记-HBase in Action-第三部分应用-(2)GIS系统

    本章介绍用HBase存储.高效查询地理位置信息. Geohash空间索引 考虑LBS应用中常见的两个问题:1)查找离某地近期的k个地点.2)查找某区域内地点. 假设要用HBase实现高效查找,首先要考 ...

  7. [读书笔记]算法(Sedgewick著)·第二章.初级排序算法

    本章开始学习排序算法 1.初级排序算法 先从选择排序和插入排序这两个简单的算法开始学习排序算法.选择排序就是依次找到当前数组中最小的元素,将其和第一个元素交换位置,直到整个数组有序. public s ...

  8. 《Linux内核》课本读书笔记 第一章、第二章

  9. Python基础教程 读书笔记(2)第二章 列表和元组

    2.1序列概览 列表和元组的主要区别在于,列表可以修改,元组则不能.也就是说如果要根据要求来添加元素,那么列表可能会更好用;而出于某些原因,序列不能修改的时候,使用元组则更为合适.使用后者的理由通常是 ...

随机推荐

  1. hdu5067Harry And Dig Machine(TSP旅行商问题)

    题目链接: huangjing 题意:给出一幅图.图中有一些点,然后从第1个点出发,然后途径全部有石头的点.最后回到原点,然后求最小距离.当初作比赛的时候不知道这就是旅行商经典问题.回来学了一下. 思 ...

  2. 动态从数据库读取菜单(ASP.NET版)

    这几天一直打算做个从数据读取导航菜单的效果,以前做的时候都是写死的(太死了),好了话不多说,先看效果! 我是个小菜,高手请不要喷!我在网上查了好久,说用menu控件,但是我用了不太好!最后我决定用re ...

  3. 动软代码生成V2.74模版简介

    最近发现很多人用动软代码生成,确实方便,有些经验记录下,以后查看回顾. ..\Maticsoft\Codematic2\Template\TemplateFile 为模板文件夹,直接在目录下新建文件夹 ...

  4. No suitable authentication method found to complete authentication (publickey,keyboard-interactive).

    string command = Command.Text; StringBuilder result = new StringBuilder(); try { var connectionInfo ...

  5. HTML5 Canvas显示本地图片实例1、Canvas预览图片实例1

    1.前台代码: <input id="fileOne" type="file" /> <canvas id="canvasOne&q ...

  6. SQL Server 如何创建定时作业

    在做SQL server 管理时,往往需要每日执行定时任务,但是如果每天都去人工执行,非常不方便,而且一般定时操作,都应该是在数据库压力不大时,一般是在夜间.所以我们需要创建定时作业来代替人工的执行定 ...

  7. C#方法的重载

    方法的重载 参数不同,个数可以相同 参数相同,个数不能相同 static void Main(string[] arr) { Console.WriteLine(M(,)); Console.Read ...

  8. Android 虚拟机快捷键

    何须这样麻烦,直接用快捷键就行了,你用鼠标点来点去怎么还不如用快捷键来得快:一下是快捷键: Home键(小房子键) 在键盘上映射的就是home键,这倒是很好记. Menu键 用于打开菜单的按键,在键盘 ...

  9. HTML&CSS基础学习笔记1.23-表单的文本域和下拉列表

    文本域 <textarea>标签定义多行的文本输入控件. 平时在网页上的一些需要输入比较多的内容的输入框,比如回复帖子,回答问题等,都可以用<textarea>标签. < ...

  10. Centos common software install

    1.本地安装soft yum localinstall xxx.rpm 2.kolourpaintyum install kolourpaint