HBase学习之路(五):理解过滤器的概念及比较过滤器的使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41955099/article/details/97885871

一、过滤器简介

1.过滤器的基本概念

  • 过滤器是HBase为客户端提供的一种高级API,是HBase的一种高级特性,它提供了非常强大的功能帮助用户处理表中的数据。HBase中读取数据的API主要是get()和scan(),它们都支持直接读取数据和通过指定起始行健访问数据的功能,可以通过添加限定条件如列族、列、时间戳等来限制查询的数量,但是它们缺少一种细粒度的的筛选功能,比如基于正则表达式的筛选。由此诞生过滤器,Get类和Scan类都支持过滤器,通过方法setFilter(Filter filter)可以设置查询时的过滤器。
  • 过滤器是在服务端生效的,换言之过滤器并不是在查询结束,查询结果传送回客户端后再进行条件的过滤,返回过滤后的结果,而是直接在服务端生效,进行过滤,将过滤后的数据返回给客户端,处理流程如下:
    1.客户端创建过滤器并配置好。
    2.查询时发送序列化后的过滤器给对应的RegionServer。
    3.RegionServer使用过滤器过滤数据,将过滤结果返回给客户端。
    在这里插入图片描述

2.过滤器的层次结构

  • 在过滤器的层次结构中最基本的接口是Filter,其次是抽象类FilterBase,分别实现了过滤器的空壳和骨架,FilterBase与Filter的关系是这样的:Filter定义了过滤器的所有基本方法,如果直接使用该接口则要实现大量的方法,而FilterBase实现了大部分方法,使得用户只需实现部分方法即可,因此大部分实体过滤器都是通过继承FilterBase类来实现的。

3.比较运算符

  • 在HBase中有一类过滤器继承了CompareFilter类,CompareFilter类比基类FilterBase多了一个compare()方法,它需要传入参数来定义比较操作的过程:
    在这里插入图片描述

4.运算器

  • CompareFilter类需要的第二个参数是类型是比较器,比较器提供多种方法来比较不同的键值,比较器继承于WritableByteArrayComparable,WritableByteArrayComparable实现了Writable和Comparable接口,HBase提供了如下的比较器:
    在这里插入图片描述
    后面的三种比较器,即BitComparator,RegexStringComparator,SubStringComparator,只能与EQUAL或者NOT_EQUAL运算符搭配使用,因为这些比较器的compareTo()方法只返回1或0,如果使用其他的运算符,如LESS,就会出错。

二、比较过滤器的使用

0.比较过滤器的基本概念

  • HBase提供的第一类比较器是比较过滤器(comparison filter),用户创建该过滤器实例时需要传入一个比较运算符和一个比较器,以下几个比较过滤器都有一个从CompareFilter类继承而来的方法,其方法签名是:
    CompareFilter(CompareOp valueCompareOp,WritableByteArrayComparable valueComparator)
    我们需要提供具体的比较运算符和比较器来使用它,实际上以下的几个比较器都基于此方法进行实例化。
  • HBase中的过滤器本来是为了筛掉无用的数据,被过滤掉的数据不会被传送回客户端,过滤器不用于指定用户需要哪些信息,而是在读取数据的过程中不返回用户不想要的数据,简而言之,一般而言符合过滤器要求的数据将被拦截,不符合的数据被放行。但是比较过滤器刚好相反,符合过滤条件的将被放心,不符合条件的数据将被拦截,这是值得注意的。

1.行过滤器

  • 行过滤器(RowFilter)基于行健来过滤数据,结合上文,可以知道用法就是传入一个运算符和比较器,行过滤器就会根据这两者进行数据筛选,符合这一行键条件的数据会返回客户端,假设我想查找比"row-15"大的行健所对应行的数据,核心代码为:
    // 创建扫描器实例
    Scan scan = new Scan();
    // 创建行比较过滤器,传入比较运算符和比较器
    Filter filter = new RowFilter(CompareFilter.CompareOp.GREATER
    	,new BinaryComparator(Bytes.toBytes("row-22")));
    // 为扫描器设置过滤器
    scan.setFilter(filter);
    // 进行扫描
    ResultScanner scanner = table.getScanner(scan);
    // 遍历结果
    for(Result result:scanner){
    	System.out.println(result);
    }
    scanner.close();
    
    又假设,我想查询行健中包含子串"xiao-ban-zhu"的行健,就可以使用SubstringComparator这个比较器,同时注意运算符为EQUAL,核心代码如下:
    	// 创建扫描器实例
      Scan scan = new Scan();
      // 创建行比较过滤器,传入比较运算符和比较器
      Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL
      	,new SubstringComparator("xiao-ban-zhu"));
      // 为扫描器设置过滤器
      scan.setFilter(filter);
      // 进行扫描
      ResultScanner scanner = table.getScanner(scan);
      // 遍历结果
      for(Result result:scanner){
      	System.out.println(result);
      }
      scanner.close();
    

2.列族过滤器

  • 列族过滤器(FamilyFilter)与行过滤器相似,不过它是通过比较列族而不是比较行健来返回结果的。通过使用不同组合的运算符和比较器可以在列族一级筛选数据,比如我想读取列族小于等于"xiao-15"的数据,核心代码如下:
    // 创建扫描器实例
    Scan scan = new Scan();
    // 创建列族比较过滤器,传入比较运算符和比较器
    Filter filter = new FamilyFilter(CompareFilter.CompareOp.LESS_OR_EQUAL
    	,new BinaryComparator(Bytes.toBytes("xiao-15")));
    // 为扫描器设置过滤器
    scan.setFilter(filter);
    // 进行扫描
    ResultScanner scanner = table.getScanner(scan);
    // 遍历结果
    for(Result result:scanner){
    	System.out.println(result);
    }
    scanner.close();
    

3.列名过滤器

  • 列名过滤器(QulifierFilter)与上面两个过滤器类似,只是它通过比较列名来返回结果的。之前谈过,HBase依靠几个坐标定位数据,分别是行健、列族、列名、时间戳,在这里是通过使用不同组合的运算符和比较器可以在列名一级筛选数据,比如我想筛选行健为“xiao-ban-zhu”,列名包含大写字母的列,这时候就要使用正则表达式比较器RegexStringComparator及运算符EQUAL了,其核心代码如下:
    // 创建Get实例,输入行健
    Get get = new get(Bytes.toBytes("xiao-ban-zhu"));
    // 创建列族比较过滤器,传入比较运算符和比较器
    Filter filter = new QulifierFilter(CompareFilter.CompareOp.EQUAL
    	,new RegexStringComparator("*[A-Z]*"));
    // 为扫Get实例置过滤器
    get.setFilter(filter);
    Result result = table.get(get);
    // 打印结果
    System.out.println(result);
    
    上述案例是使用Get对象获取数据,因此会将第一条符合过滤条件的数据返回,当然也可以配合Scan来使用,非常灵活。

4.值过滤器

  • 值过滤器(ValueFilter)与上述过滤器的区别在于,这个过滤器是直接针对存储的值进行过滤的,HBase采用三级坐标(行健,列族和列,时间戳)作为Key进行数据的定位与存储,上述过滤器正是对其中的某个坐标进行过滤从而筛选出值,现在是直接对值进行过滤。假设,我想查询列名中不包含子串"xiao-ban-zhu"的所有数据,核心代码如下:
    // 创建扫描器实例
    Scan scan = new Scan();
    // 创建值过滤器,传入比较运算符和比较器
    Filter filter = new ValueFilter(CompareFilter.CompareOp.NOT_EQUAL
    	,new SubstringComparator("xiao-ban-zhu"));
    // 为扫描器设置过滤器
    scan.setFilter(filter);
    // 进行扫描
    ResultScanner scanner = table.getScanner(scan);
    // 遍历结果
    for(Result result:scanner){
    	System.out.println(result);
    }
    scanner.close();
    

三、总结

  • 本文介绍了HBase中过滤器的基本概念,并就比较过滤器进行详细的介绍,比较过滤器作为HBase的第一类过滤器,继承于CompareFilter类,为用户提供了强大的比较功能,也是用的较多的一种过滤器,除此之外,还有专用过滤器,附加过滤等等,以后会进行介绍。事实上,通过Get、Scan实例配合过滤器来对表数据读取可以减少大量不必要数据在网络间的传输,提高了查询效率。感谢你的阅读,如有错误请不吝赐教!
  • 更多内容请查阅 萧邦主的技术博客导航
展开阅读全文

hbase自定义过滤器异常

06-08

写了一个hbase的过滤器例子,就对rowkey判断一下rnimport java.io.IOException;rnimport java.util.List;rnrnimport org.apache.hadoop.hbase.Cell;rnimport org.apache.hadoop.hbase.KeyValue;rnimport org.apache.hadoop.hbase.filter.FilterBase;rnrnpublic class ComterFilter extends FilterBasernrn @Overridern public boolean filterAllRemaining() throws IOException rn return super.filterAllRemaining();rn rnrn @Overridern public ReturnCode filterKeyValue(Cell ignored) throws IOException rn return super.filterKeyValue(ignored);rn rnrn @Overridern public boolean filterRow() throws IOException rn return super.filterRow();rn rnrn @Overridern public boolean filterRowKey(byte[] buffer, int offset, int length)rn throws IOException rn String rowKey = new String(buffer);rn System.out.println("rowkey====="+rowKey);rn if("01d7f40760960e7bd9443513f22ab9af".equals(rowKey))rn return true;rn elsern return false;rn rn rnrn @Overridern public void filterRowCells(List ignored) throws IOException rn super.filterRowCells(ignored);rn rn rn @Overridern public void filterRow(List arg0) rn rn rnrnrn已经修改过HBASE_CLASSPATH,并且已经重启rn但是运行时报错了,报错信息如下,有没有大牛指导一下rnSun Jun 08 17:46:43 CST 2014, org.apache.hadoop.hbase.client.RpcRetryingCaller@6cb107fd, java.io.IOException: java.io.IOException: java.lang.reflect.InvocationTargetExceptionrn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1297)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toScan(ProtobufUtil.java:886)rn at org.apache.hadoop.hbase.regionserver.HRegionServer.scan(HRegionServer.java:3005)rn at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:26929)rn at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2185)rn at org.apache.hadoop.hbase.ipc.RpcServer$Handler.run(RpcServer.java:1889)rnCaused by: java.lang.reflect.InvocationTargetExceptionrn at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)rn at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)rn at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)rn at java.lang.reflect.Method.invoke(Method.java:597)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1295)rn ... 5 morernCaused by: org.apache.hadoop.hbase.exceptions.DeserializationException: parseFrom called on base Filter, but should be called on derived typern at org.apache.hadoop.hbase.filter.Filter.parseFrom(Filter.java:266)rn ... 10 morernrnSun Jun 08 17:46:43 CST 2014, org.apache.hadoop.hbase.client.RpcRetryingCaller@6cb107fd, java.io.IOException: java.io.IOException: java.lang.reflect.InvocationTargetExceptionrn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1297)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toScan(ProtobufUtil.java:886)rn at org.apache.hadoop.hbase.regionserver.HRegionServer.scan(HRegionServer.java:3005)rn at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:26929)rn at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2185)rn at org.apache.hadoop.hbase.ipc.RpcServer$Handler.run(RpcServer.java:1889)rnCaused by: java.lang.reflect.InvocationTargetExceptionrn at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)rn at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)rn at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)rn at java.lang.reflect.Method.invoke(Method.java:597)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1295)rn ... 5 morernCaused by: org.apache.hadoop.hbase.exceptions.DeserializationException: parseFrom called on base Filter, but should be called on derived typern at org.apache.hadoop.hbase.filter.Filter.parseFrom(Filter.java:266)rn ... 10 morernrnSun Jun 08 17:46:44 CST 2014, org.apache.hadoop.hbase.client.RpcRetryingCaller@6cb107fd, java.io.IOException: java.io.IOException: java.lang.reflect.InvocationTargetExceptionrn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1297)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toScan(ProtobufUtil.java:886)rn at org.apache.hadoop.hbase.regionserver.HRegionServer.scan(HRegionServer.java:3005)rn at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:26929)rn at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2185)rn at org.apache.hadoop.hbase.ipc.RpcServer$Handler.run(RpcServer.java:1889)rnCaused by: java.lang.reflect.InvocationTargetExceptionrn at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)rn at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)rn at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)rn at java.lang.reflect.Method.invoke(Method.java:597)rn at org.apache.hadoop.hbase.protobuf.ProtobufUtil.toFilter(ProtobufUtil.java:1295)rn ... 5 morernCaused by: org.apache.hadoop.hbase.exceptions.DeserializationException: parseFrom called on base Filter, but should be called on derived typern at org.apache.hadoop.hbase.filter.Filter.parseFrom(Filter.java:266)rn ... 10 morernrnrnrn 论坛

没有更多推荐了,返回首页