- 浏览: 270485 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
muyufenghua:
public static <T super B> ...
浅谈Java泛型中的extends和super关键字 -
wantodare:
class Test1 {
{
a=1;
}
pr ...
Java对象初始化详解 -
wubo2qml:
问下如何进行列中数字大小的比较。我看了几个过滤器,最接近的是S ...
利用Filter进行HBase查询 -
blackproof:
rowkey是A_B我知道要的A集合,也知道要的B范围不用自定 ...
利用Filter进行HBase查询 -
bin_1715575332:
文章不错,尤其了后半部分讲解一些原理。
利用Filter进行HBase查询
在HBase中,我们可以利用其Scan接口对数据进行扫描,具体方式如下,
在扫描过程中,我们想要哪些数据返回哪些数据不返回是用过Scan这个类提供的各种方法来控制的,下面列出了一些主要的方法,
其中最为有用的是setFilter方法,这个方法允许我们为扫描过程设置一个过滤器,从而过滤掉那些不符合要求的记录。Filter机制非常灵活,基本可以满足我们所有的查询需求。HBase的类库中已经预先定义了很多的Filter,通过使用这些预定义的Filter,我们可以非常灵活地组装自己的查询需求。但是依赖于Hbase对Filter的实现机制,还是会存在一些限制,这个下面马上就会说到。
HBase是如何实现Filter的
HBase提供了一个Java实现的客户端,用来与服务器进行通讯。这个客户端的通讯层使用了RPC来进行封装,封装所有RPC操作的是org.apache.hadoop.hbase.ipc.HBaseRPC,而这个类会将真正的通讯委托给org.apache.hadoop.hbase.ipc.HBaseClient类来执行。如果跟踪开头给出的代码中的第二行代码的执行,会发现其执行流程是这样的,
上图中的ScannerCallable.openScanner()方法如下,
其中server属性的类型是HRegionInterface,从调用栈可以看到这个接口被动态代理掉了,最终的调用会委托给HBaseRPC执行,也就是我们看到的调用栈最顶端的那行代码。检查HRegionInterface接口提供的方法,会发现其主要是用来与HBase的RegionServer进行交互的(HBase的RegionServer就是真正存放数据的服务器)。在HBaseRPC接受openScanner这个方法调用之后,它会委托HBaseClient去与各个RegionServer进行通信,告诉它们有个客户端 正在发起openScanner方法调用,同时会把openScanner方法的参数序列化之后传给各个RegionServer。这个方法调用成功之后(HBase客户端收到了所有RegionServer的正确相应),openScanner方法就返回了。
如果本文开头代码所示,第三行之后的代码就开始从扫描器中拿结果了。这个时候HBase客户端会逐个与RegionServer进行通信,告诉它们开始扫描吧。由于在openScanner的时候,已经把参数传递给了各个RegionServer,各个RegionServer就可以根据参数来执行扫描了,然后将扫描结果返回给HBase客户端,然后客户端程序就可以拿到结果进行处理了。
HBase中的Filter有何限制
从ScannerCallable.openScanner的参数可以看到,HBase客户端其实是把客户端程序中创建的Scan对象当作参数传递给通讯层的,也就是说这个Scan参数会被序列化给各个RegionServer,当然也就包括设置在其中的Filter。
继续跟踪代码会发现,对参数执行序列化操作的代码是放在HBaseClient的一个叫做Connection的内部类中的sendParam方法中的,其代码如下,
我们会发现这个方法会调用Call对象中的param属性的write方法,目的是让param属性自己将自己转换成字节,然后放入DataOutputBuffer里面。在ScannerCallable.openScanner()方法中,这个param就是Scan对象,通过查看Scan对象的源代码,我们发现这个对象实现了HBase的Writable接口,因此确实有一个write方法,这个方法的代码如下,
这个方法会把Scan对象中的所有在RegionServer执行扫描过程中需要用到的参数全部写入DataOutput中,当然也包括Filter。从这个代码中,我们很容易地知道HBase中的Filter也是实现了Writable接口的。而且在写入Filter对象本身的byte之前,还会往输出流中写入这个Filter的类名,这一步是必须的,否则RegionServer将无法知道它们需要使用哪一个Filter。正式由于这一点,给用户自定义Filter带来了限制。由于真正的扫描数据的过程是在RegionServer上发生的,HBase就采用这种序列化的方式将扫描数据需要用到的类和属性告知RegionServer。对于用户自定义的Filter,由于在RegionServer上是找不到相关类的,因此在执行的过程中会抛出异常。也许有人会说,把自定义的Filter放到各个RegionServer上去不就可以了吗?这样做确实可以,但是维护成本会比较大,而且自定义Filter有时候也不是那么好些的,因为会设置到序列化自身。因此我们还是应该使用HBase已经提供的Filter,如果能够合理有效地组合预定义的各个Filter,是足够用来实现我们的查询需求的。
Scan scanConfig = new Scan(); ResultScanner scanner = table.getScanner(scanConfig); for (Result result : scanner) {//ResultScanner实现了Iterator接口 //do something here }
在扫描过程中,我们想要哪些数据返回哪些数据不返回是用过Scan这个类提供的各种方法来控制的,下面列出了一些主要的方法,
/** * 返回指定列族下的指定qualifier中的值 */ public Scan addColumn(byte[] family, byte[] qualifier) /** * 设置扫描的起始行,starRow是存储时候用的rowKey */ public Scan setStartRow(byte[] startRow) /** * 设置扫描的结束行,stopRow是存储时候用的rowKey */ public Scan setStopRow(byte[] stopRow) /** * 设置返回结果的时间戳 */ public Scan setTimeStamp(long timestamp) /** * 设置返回结果的时间戳返回 */ public Scan setTimeRange(long minStamp, long maxStamp) /** * 设置过滤器,这是非常灵活的扫描机制 */ public Scan setFilter(Filter filter)
其中最为有用的是setFilter方法,这个方法允许我们为扫描过程设置一个过滤器,从而过滤掉那些不符合要求的记录。Filter机制非常灵活,基本可以满足我们所有的查询需求。HBase的类库中已经预先定义了很多的Filter,通过使用这些预定义的Filter,我们可以非常灵活地组装自己的查询需求。但是依赖于Hbase对Filter的实现机制,还是会存在一些限制,这个下面马上就会说到。
HBase是如何实现Filter的
HBase提供了一个Java实现的客户端,用来与服务器进行通讯。这个客户端的通讯层使用了RPC来进行封装,封装所有RPC操作的是org.apache.hadoop.hbase.ipc.HBaseRPC,而这个类会将真正的通讯委托给org.apache.hadoop.hbase.ipc.HBaseClient类来执行。如果跟踪开头给出的代码中的第二行代码的执行,会发现其执行流程是这样的,
上图中的ScannerCallable.openScanner()方法如下,
protected long openScanner() throws IOException { return this.server.openScanner(this.location.getRegionInfo().getRegionName(), this.scan); }
其中server属性的类型是HRegionInterface,从调用栈可以看到这个接口被动态代理掉了,最终的调用会委托给HBaseRPC执行,也就是我们看到的调用栈最顶端的那行代码。检查HRegionInterface接口提供的方法,会发现其主要是用来与HBase的RegionServer进行交互的(HBase的RegionServer就是真正存放数据的服务器)。在HBaseRPC接受openScanner这个方法调用之后,它会委托HBaseClient去与各个RegionServer进行通信,告诉它们有个客户端 正在发起openScanner方法调用,同时会把openScanner方法的参数序列化之后传给各个RegionServer。这个方法调用成功之后(HBase客户端收到了所有RegionServer的正确相应),openScanner方法就返回了。
如果本文开头代码所示,第三行之后的代码就开始从扫描器中拿结果了。这个时候HBase客户端会逐个与RegionServer进行通信,告诉它们开始扫描吧。由于在openScanner的时候,已经把参数传递给了各个RegionServer,各个RegionServer就可以根据参数来执行扫描了,然后将扫描结果返回给HBase客户端,然后客户端程序就可以拿到结果进行处理了。
HBase中的Filter有何限制
从ScannerCallable.openScanner的参数可以看到,HBase客户端其实是把客户端程序中创建的Scan对象当作参数传递给通讯层的,也就是说这个Scan参数会被序列化给各个RegionServer,当然也就包括设置在其中的Filter。
继续跟踪代码会发现,对参数执行序列化操作的代码是放在HBaseClient的一个叫做Connection的内部类中的sendParam方法中的,其代码如下,
protected void sendParam(Call call) { if (shouldCloseConnection.get()) { return; } DataOutputBuffer d=null; try { //noinspection SynchronizeOnNonFinalField synchronized (this.out) { // FindBugs IS2_INCONSISTENT_SYNC if (LOG.isDebugEnabled()) LOG.debug(getName() + " sending #" + call.id); //for serializing the //data to be written d = new DataOutputBuffer(); d.writeInt(0xdeadbeef); // placeholder for data length d.writeInt(call.id); call.param.write(d); byte[] data = d.getData(); int dataLength = d.getLength(); // fill in the placeholder Bytes.putInt(data, 0, dataLength - 4); out.write(data, 0, dataLength); out.flush(); } } catch(IOException e) { markClosed(e); } finally { //the buffer is just an in-memory buffer, but it is still polite to // close early IOUtils.closeStream(d); } }
我们会发现这个方法会调用Call对象中的param属性的write方法,目的是让param属性自己将自己转换成字节,然后放入DataOutputBuffer里面。在ScannerCallable.openScanner()方法中,这个param就是Scan对象,通过查看Scan对象的源代码,我们发现这个对象实现了HBase的Writable接口,因此确实有一个write方法,这个方法的代码如下,
public void write(final DataOutput out) throws IOException { out.writeByte(SCAN_VERSION); Bytes.writeByteArray(out, this.startRow); Bytes.writeByteArray(out, this.stopRow); out.writeInt(this.maxVersions); out.writeInt(this.batch); out.writeInt(this.caching); out.writeBoolean(this.cacheBlocks); if(this.filter == null) { out.writeBoolean(false); } else { out.writeBoolean(true); Bytes.writeByteArray(out, Bytes.toBytes(filter.getClass().getName())); filter.write(out); } tr.write(out); out.writeInt(familyMap.size()); for(Map.Entry<byte [], NavigableSet<byte []>> entry : familyMap.entrySet()) { Bytes.writeByteArray(out, entry.getKey()); NavigableSet<byte []> columnSet = entry.getValue(); if(columnSet != null){ out.writeInt(columnSet.size()); for(byte [] qualifier : columnSet) { Bytes.writeByteArray(out, qualifier); } } else { out.writeInt(0); } } }
这个方法会把Scan对象中的所有在RegionServer执行扫描过程中需要用到的参数全部写入DataOutput中,当然也包括Filter。从这个代码中,我们很容易地知道HBase中的Filter也是实现了Writable接口的。而且在写入Filter对象本身的byte之前,还会往输出流中写入这个Filter的类名,这一步是必须的,否则RegionServer将无法知道它们需要使用哪一个Filter。正式由于这一点,给用户自定义Filter带来了限制。由于真正的扫描数据的过程是在RegionServer上发生的,HBase就采用这种序列化的方式将扫描数据需要用到的类和属性告知RegionServer。对于用户自定义的Filter,由于在RegionServer上是找不到相关类的,因此在执行的过程中会抛出异常。也许有人会说,把自定义的Filter放到各个RegionServer上去不就可以了吗?这样做确实可以,但是维护成本会比较大,而且自定义Filter有时候也不是那么好些的,因为会设置到序列化自身。因此我们还是应该使用HBase已经提供的Filter,如果能够合理有效地组合预定义的各个Filter,是足够用来实现我们的查询需求的。
评论
3 楼
wubo2qml
2013-11-22
问下如何进行列中数字大小的比较。我看了几个过滤器,最接近的是
SingleColumnValueFilter 但是这个里面的过滤器是按照字典顺序进行比较的!
SingleColumnValueFilter 但是这个里面的过滤器是按照字典顺序进行比较的!
2 楼
blackproof
2013-08-12
rowkey是A_B
我知道要的A集合,也知道要的B范围
不用自定义,怎么Filter呢
我知道要的A集合,也知道要的B范围
不用自定义,怎么Filter呢
1 楼
bin_1715575332
2013-05-06
文章不错,尤其了后半部分讲解一些原理。
发表评论
-
Dremel对现有map-reduce的改进
2012-08-22 17:49 1755Google在2010年的时候对外公布了其使用的一个大数据交互 ... -
Change Mac OS X user Limits
2012-08-14 16:29 4697如何修改max os x关于用户的配额限制,主要是进程数和文件 ... -
mac os x hosts文件重置
2012-08-05 16:52 4644在做本地web开发的时候,我们需要绑定hosts,用来将本地i ... -
Java对象初始化详解
2012-07-18 00:43 26928在Java中,一个对象在可 ... -
Java中Enum类型的序列化
2012-07-07 21:53 30645在Java中,对Enum类型的序列化与其他对象类型的序列化有所 ... -
Java final关键字详解
2012-07-07 16:27 3991在java中,final关键字可以有如下的用处: final ... -
利用线程隔离简化并发控制
2012-06-28 01:18 2232在Java中,为了限制多个不同线程对共享变量或者状态的访问,利 ... -
Java内存模型能给我们什么
2012-06-24 15:07 1518首先,为什么需要有内 ... -
java方法调用过程解析和执行--编译器的处理
2012-06-02 15:24 2963本文尝试对java在编译器和运行期如何处理程序代码中的方法调用 ... -
maven杂记
2012-03-02 00:32 2020单独部署一个文件到repo 有时候我们会需要单独部署一个文件到 ... -
浅谈Java泛型中的extends和super关键字
2010-12-25 21:06 18928泛型是在Java 1.5中被加入了,这里不讨论泛型的细节 ... -
TCP的状态变迁
2010-12-16 21:36 1969TCP的状态变迁图,做个 ... -
Java xml处理概述
2010-12-14 18:21 1558在Java中,对xml的处理模型主要有两种,一种DOM,一种是 ... -
字符集与编码-概念区分
2010-03-23 13:50 1167在这里主要记录一下 ... -
Sun的apt工具及Mirrors包学习
2010-01-05 00:02 4116最近看来一些有关Java Annotation的东西,主要 ... -
Inversion of Control Containers and the Dependency Injection pattern
2009-12-02 23:02 999One of the entertaining things ... -
Java中Soft,Weak,Phantom应用的区别和使用
2009-10-29 13:20 2370Java 1.2版本之后加入 ... -
java 反射实例化内部类
2009-08-25 13:51 5884内部类的初始化同一般类的初始化基本相同,只是内部类的类名全 ... -
java 泛型-erasure
2009-07-30 12:42 2587Java的泛型实现采用了擦除(erasure)机制,这给获 ... -
Java语言深入:深入研究Java equals方法
2009-07-28 11:43 1117equals方法的重要性毋 ...
相关推荐
因为面向列的特点,Hbase只能单单地以rowkey为主键作查询,而无法对表进行多维查询和join操作,并且查询通常都是全表扫描,耗费资源较大,查询效率较低。类比于传统型数据库里的一些查询方式,本文对Hbase的存储原理进行了...
hbase分页查询实现.pdf
hbase查询分页分页
1、有多个工具可选择使用
hbase分页查询实现
很有效的hbase查询方法,我觉得很有用,供大家参考下,共同研究
里面包括了特定场合下,HBase随机查询的一些性能指标参考以及调优策略
hbase分页查询实现[归类].pdf
java 利用 sping-data-hadoop HbaseTemplate 操作hbase find get execute 等方法 可以直接运行
本文当是一个基于HBase的海量数据的实实时查询系统的原理分析。详细的介绍了大数据查询的原理。
hbase java api 访问 查询、分页 详情请看:http://blog.csdn.net/wild46cat/article/details/53321409
HBase shell的基本用法
HBase即Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在普通的PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实现,类似Google Bigtable利用...
springboot搭建的hbase可视化界面 支持hbase的建表与删除 支持根据rowkey查询数据
Phoniex 可以让开发者在HBase数据集上使用SQL查询。Phoenix查询引擎会将SQL查询转换为一个或多个HBase scan,并编排执行以生成标准的JDBC结果集,对于简单查询来说,性能甚至胜过Hive。 标签:Phoniex
搭建pinpoint需要的hbase初始化脚本hbase-create.hbase
Hbase笔记 —— 利用JavaAPI的方式操作Hbase数据库(往hbase的表中批量插入数据)
5 5)最后,HBase不支持联合查询 5 mapreduce与HBase表配合使用 5 4. HBase的模式Schema设计的一些概念和原则 5 1)模式的创建与更新 5 2)列族的数量 6 3)行键设计RowKey 6 5. HBase的拓扑结构是什么? 7 1)拓扑...
Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询
多线程 hbase