Hadoop学习四十二:HBase 过滤器

一.概述

  1. 客户端创建包含过滤器Filter的Scan。
  2. Scan通过RPC被发送给RegionServer,在服务器端执行过滤操作。
  3. Scan的作用域是region,所以一个RegionServer有多个region的话,Scan将被发送到每个region。

 

二.Filter工作流程

 

     你必须知道的是,HBase里的一行数据对应一或者多个KeyValue。再来看看流程。

  1. boolean fiterRowKey(byte[] buffer, int offset, int length):检查rowkey。返回true代表被过滤掉,false进入下个方法。
  2. ReturnCode fiterKeyValue(KeyValue v):检查rowkey下特定的某一个KeyValue。它有五种返回值,常见的ReturnCode.INCLUDE代表结果中包含这个KeyValue,Skip代表不包含,继续下处理一个KeyValue。
  3. void filterRow(List<KeyValue> ignored):ignored是2里面被过滤掉的KeyValue集合。
  4. boolean filterRow():返回true代表过滤掉当前行。
  5. void reset():迭代每一个新的RowKey(步骤1)前调用此方法。
  6. boolean filterAllRemaining():返回true时代表终止整个扫描操作。如用户找到了需要的所有数据,就在这里可以返回true。

三.例子

      说这么多,不如一个实际的例子来的方便。

      用户表rowkey为用户名称,cf:age代表年龄,cf:pw代表密码。现在需要找出用户,有三个限制条件

  1. 看到zzy这个用户直接pass,因为它是个技术狂人酷
  2. 找出密码长度小于4的用户,用户信息不需要包含pw列。
  3. 只找出满足上述条件的两个用户。
    public class PasswordStrengthFilter extends FilterBase {
    	
    	private int len;
    	private int limit;
    	private int rowsAccepted = 0;
    	private boolean filterRow = false;
    
    	public PasswordStrengthFilter() {
    		super();
    	}
    
    	public PasswordStrengthFilter(int len, int limit) {
    		this.len = len;
    		this.limit = limit;
    	}
    
    	@Override
    	public boolean filterRowKey(byte[] buffer, int offset, int length) {
    		String rowkey = Bytes.toString(buffer, offset, length);
    		boolean iszzy = rowkey.equals("zzy");
    		return iszzy;
    	}
    
    	public ReturnCode filterKeyValue(KeyValue v) {
    		if (Bytes.toString(v.getQualifier()).equals("pw")) {
    			if (v.getValueLength() >= len) {
    				this.filterRow = true;
    			}
    			return ReturnCode.SKIP;
    		}
    		return ReturnCode.INCLUDE;
    	}
    
    	@Override
    	public void filterRow(List<KeyValue> ignored) {
    	}
    	
    	public boolean filterRow() {
    		if(!filterRow){
    			rowsAccepted ++ ;
    		}
    		return this.filterRow;
    	}
    	
    	@Override
    	public boolean filterAllRemaining() {
    		return rowsAccepted >= limit;
    	}
    
    	public void reset() {
    		this.filterRow = false;
    	}
    
    	public void write(DataOutput out) throws IOException {
    		out.writeInt(len);
    		out.writeInt(limit);
    	}
    
    	public void readFields(DataInput in) throws IOException {
    		this.len = in.readInt();
    		this.limit = in.readInt();
    	}
    	
    	public static String getShortDes(KeyValue kv){
    		return "KeyValue["+Bytes.toString(kv.getRow()) + "\t" + Bytes.toString(kv.getFamily()) + ":" + Bytes.toString(kv.getQualifier()) + "=" + Bytes.toString(kv.getValue())+"]";
    	}
    }
     

     new PasswordStrengthFilter(4, 2)的测试结果:请各位自己分析下每一行,每一个KeyValue是怎么被fiter处理的。

input:
addData("david", TN, "age", "12");
addData("david", TN, "pw", "p1");
addData("zzy", TN, "age", "13");
addData("zzy", TN, "pw", "p2");
addData("zzz", TN, "age", "18");
addData("zzz", TN, "pw", "p456");
addData("zzzz", TN, "age", "18");
addData("zzzz", TN, "pw", "p4");
addData("zzzzz", TN, "age", "11");
addData("zzzzz", TN, "pw", "p6");

output:
KeyValue[david	cf:age=12]
KeyValue[zzzz	cf:age=18]

      

 

四.总结

  1. 一般返回true代表被过滤掉。
  2. 一个region上的所有数据共享一个Filter,并不是每来一行数据就new一个Filter来处理。所以例子中的rowsAccepted得以生效,变量filterRow的状态需要重置。

 

     附件为测试代码和一个根据rowkey分页的RowPaginationFilter

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值