Hbase 学习(三)Coprocessors
Coprocessors
之前我们的filter都是在客户端定义,然后传到服务端去执行的,这个Coprocessors是在服务端定义,在客户端调用,然后在服务端执行,他有点儿想我们熟悉的存储过程,传一些参数进去,然后进行我们事先定义好的操作,我们常常用它来做一些比如二次索引啊,统计函数什么的,它也和自定义filter一样,需要事先定好,然后在hbase-env.sh中的HBASE_CLASSPATH中指明,就像我的上一篇中的写的那样。
Coprocessors分两种,observer和endpoint。
(1)observer就像触发器一样,当某个事件发生的时候,它就出发。
已经有一些内置的接口让我们去实现,RegionObserver、MasterObserver、WALObserver,看名字就大概知道他们是干嘛的。
(2)endpoint可以认为是自定义函数,可以把这个理解为关系数据库的存储过程。
所有的Coprocessor都是实现自Coprocessor 接口,它分SYSTEM和USER,前者的优先级比后者的优先级高,先执行。
它有两个方法,start和stop方法,两个方法都有一个相同的上下文对象CoprocessorEnvironment。
void start(CoprocessorEnvironment env) throws IOException;
void stop(CoprocessorEnvironment env) throws IOException;这是CoprocessorEnvironment的方法。
Working with Tables
对表进行操作的时候,必须先调用getTable方法活得HTable,不可以自己定义一个HTable,目前貌似没有禁止,但是将来会禁止。
并且在对表操作的时候,不能对行加锁。
Coprocessor Loading
Coprocessor加载需要在配置文件里面全局加载,比如在hbase-site.xml中设置。
<property> <name>hbase.coprocessor.region.classes</name> <value>coprocessor.RegionObserverExample,coprocessor.AnotherCoprocessor</value> </property> <property> <name>hbase.coprocessor.master.classes</name> <value>coprocessor.MasterObserverExample</value> </property> <property> <name>hbase.coprocessor.wal.classes</name> <value>coprocessor.WALObserverExample,bar.foo.MyWALObserver</value> </property>我们自定义的时间可以注册到三个配置项上,分别是hbase.coprocessor.region.classes,hbase.coprocessor.master.classes,
hbase.coprocessor.wal.classes上,他们分别负责region,master,wal,注册到region的要特别注意小心,因为它是针对所有表的。
<property> <name>hbase.coprocessor.region.classes</name> <value>coprocessor.RegionObserverExample</value> </property>注册到这三个触发器上,可以监控到几乎所有我们的操作上面,非常恐怖。。可以说是想要什么就有什么,详细的代码大家自己去摸索。
EndPoint的可以用来定义聚合函数,我们可以调用CoprocessorProtocol中的方法来实现我们的需求。
调用coprocessorProxy() 传一个单独的row key,这是在单独一个region上操作的。
要在所有region上面操作,我们要调用coprocessorExec()方法 传一个开始row key 和结束row key。
Demo
说了那么多废话,我都不好意思再说了,来个例子吧,统计行数的。
public interface RowCountProtocol extends CoprocessorProtocol { long getRowCount() throws IOException; long getRowCount(Filter filter) throws IOException; long getKeyValueCount() throws IOException; }public class RowCountEndpoint extends BaseEndpointCoprocessor implements RowCountProtocol { private long getCount(Filter filter, boolean countKeyValues) throws IOException { Scan scan = new Scan(); scan.setMaxVersions(); if (filter != null) { scan.setFilter(filter); } RegionCoprocessorEnvironment environment = (RegionCoprocessorEnvironment) getEnvironment(); // use an internal scanner to perform scanning. InternalScanner scanner = environment.getRegion().getScanner(scan); ; try { List<KeyValue> curVals = new ArrayList<KeyValue>(); boolean done = false; do { curVals.clear(); done = scanner.next(curVals); result += countKeyValues ? curVals.size() : ; } while (done); } finally { scanner.close(); } return result; } @Override public long getRowCount() throws IOException { return getRowCount(new FirstKeyOnlyFilter()); } @Override public long getRowCount(Filter filter) throws IOException { return getCount(filter, false); } @Override public long getKeyValueCount() throws IOException { return getCount(null, true); } }
写完之后,注册一下吧。
<property> <name>hbase.coprocessor.region.classes</name> <value>coprocessor.RowCountEndpoint</value> </property>
JAVA 客户端调用
在服务端定义之后,我们怎么在客户端用java代码调用呢,看下面的例子你就明白啦!
public class EndPointExample { public static void main(String[] args) throws IOException { Configuration conf = HBaseConfiguration.create(); HTable table = new HTable(conf, "testtable"); try { Map<byte[], Long> results = table.coprocessorExec( RowCountProtocol.class, null, null, new Batch.Call<RowCountProtocol, Long>() { @Override public Long call(RowCountProtocol counter) throws IOException { return counter.getRowCount(); } }); long total = 0; for (Map.Entry<byte[], Long> entry : results.entrySet()) { total += entry.getValue().longValue(); System.out.println("Region: " + Bytes.toString(entry.getKey()) + ", Count: " + entry.getValue()); } System.out.println("Total Count: " + total); } catch (Throwable throwable) { throwable.printStackTrace(); } } }通过table的coprocessorExec方法调用,然后调用RowCountProtocol接口的getRowCount()方法。
然后遍历每个Region返回的结果,合起来就是最终的结果,打印结果如下。
Region: testtable,,1303417572005.51f9e2251c29ccb2...cbcb0c66858f., Count: 2 Region: testtable,row3,1303417572005.7f3df4dcba3f...dbc99fce5d87., Count: 3 Total Count: 5
在上面的例子当中,我们是用Batch.Call()方法来调用接口当中的方法,我们可以用另外一个方法来简化上述代码,来看例子。
Batch.Call call =Batch.forMethod(RowCountProtocol.class,"getKeyValueCount"); Map<byte[], Long> results = table.coprocessorExec(RowCountProtocol.class, null, null, call);
采用Batch.Call方法调用同时调用多个方法
Map<byte[], Pair<Long, Long>> results =table.coprocessorExec( RowCountProtocol.class, null, null, new Batch.Call<RowCountProtocol, Pair<Long, Long>>() { public Pair<Long, Long> call(RowCountProtocol counter) throws IOException { return new Pair(counter.getRowCount(),counter.getKeyValueCount()); } }); long totalRows = 0; long totalKeyValues = 0; for (Map.Entry<byte[], Pair<Long, Long>> entry :results.entrySet()) { totalRows += entry.getValue().getFirst().longValue(); totalKeyValues +=entry.getValue().getSecond().longValue(); System.out.println("Region: " +Bytes.toString(entry.getKey()) +", Count: " + entry.getValue()); } System.out.println("Total Row Count: " + totalRows); System.out.println("Total KeyValue Count: " +totalKeyValues);
调用coprocessorProxy()在单个region上执行
RowCountProtocol protocol = table.coprocessorProxy(RowCountProtocol.class, Bytes.toBytes("row4")); long rowsInRegion = protocol.getRowCount(); System.out.println("Region Row Count: " +rowsInRegion);上面这个例子是查找row4行所在region的数据条数,这个可以帮助我们统计每个region上面的数据分布。
Hbase 学习(三)Coprocessors的更多相关文章
- Hbase学习(三)过滤器 java API
Hbase学习(三)过滤器 HBase 的基本 API,包括增.删.改.查等. 增.删都是相对简单的操作,与传统的 RDBMS 相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根 ...
- HBase学习笔记之HBase的安装和配置
HBase学习笔记之HBase的安装和配置 我是为了调研和验证hbase的bulkload功能,才安装hbase,学习hbase的.为了快速的验证bulkload功能,我安装了一个节点的hadoop集 ...
- HBASE学习笔记(四)
这两天把要前几天的知识点回顾一下,接下来我会用自己对知识点的理解来写一些东西 一.知识点回顾 1.hbase集群启动:$>start-hbase.sh ===>hbase-daemon.s ...
- HBase学习(四) 二级索引 rowkey设计
HBase学习(四) 一.HBase的读写流程 画出架构 1.1 HBase读流程 Hbase读取数据的流程:1)是由客户端发起读取数据的请求,首先会与zookeeper建立连接2)从zookeepe ...
- HBase学习(一) 基本概念和安装基本命令
HBase学习(一) 一.了解HBase 官方文档:https://hbase.apache.org/book.html 1.1 HBase概述 HBase 是一个高可靠性.高性能.面向列.可伸缩的分 ...
- HTTP学习三:HTTPS
HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...
- TweenMax动画库学习(三)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) ...
- Struts2框架学习(三) 数据处理
Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...
- 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化
1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...
- DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
随机推荐
- 怎么在eclipse中安装svn插件
Subclipse Subclipse is an Eclipse Team Provider plug-in providing support for Subversion within th ...
- kibana显示报错
"status": 500, "reason": "ElasticsearchException[org.elasticsear ...
- 关于 Xcode 调试工具 GDB and LLDB
xcode 5 好像弃用了GDB .而默认使用苹果自己开发的调试工具 LLDB. http://iosre.com/forum.php?mod=viewthread&tid=52 LLD ...
- 解决Maven->update project 恢复为默认jdk1.5以及One or more constraints have not been satisfied问题
使用maven架构创建dynamic web 项目之后,默认指定的jdk 和compilerVersion都非常古老,而且即便你手动更新了版本之后,每次update project都会复位,非常不爽. ...
- 在c/c++中浮点数是否为0的判断
在c/c++中,因为浮点数在内存中的表示是不精确的,会有很微小的误差,所以判断是否为0,就看它的绝对值是不是<=eps. eps可以看成是epsilon的缩写,可以用来表示一个无穷小的量,通常取 ...
- Netty服务器线程模型概览
一切从ServerBootstrap开始 ServerBootstrap负责初始话netty服务器,并且开始监听端口的socket请求. bootstrap bootstrap =newServerB ...
- Java设计模式之工厂模式的两种实现方式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 1. 为什么要有工厂模式? "Talk i ...
- Atitit 转移特效attilax总结
Atitit 转移特效attilax总结 总结一般从按钮,转移到大点的方框上回比较好看点.. <!--jq ui--> <style type="text/css" ...
- 互联网创业原则与创业模式attilax大总结
互联网创业原则与创业模式attilax大总结 1. 适合普通人的的创业模式1 1.1. 网络创业 兼职创业 概念创业 团队 创业 内部创业..1 2. 创业模式大总结1 2.1. 工作室创业1 2 ...
- ios 精简日历
网上其他人写的日历类功能都很齐全,比较繁杂,对于想看看日历基础实现然后自己绘制日历的我来说不太方便,就自己整理了一个极精简的日历出来,大家看了之后应该能多少理解日历该怎么自定义,很简单. 我的小dem ...
