Hbase自定义比较器

前言 常用的六种Hbase自带的比较器:

1.BinaryComparator 使用Bytes.compareTo()比较当前值与阈值

2.BinaryComparator  类似第一种,但它从左端开始前缀匹配

3.NullComparator 只判断当前值是否是null

4.BitComparator 通过位运算操作执行位级比较

5.RegexStringComparator 根据正则表达式去匹配

6.SubStringComparator 将数据转为string,使用string的contains方法进行匹配
 

注意:后三种比较器只能与EQUAL和NOT_EQUAL运算符搭配使用,即不能进行GREATER或LESS比较运算,会产生错误。      

————摘自《Hbase权威指南》P131-P132

 

虽然HBASE提供了这么多自带的比较器,但个人感觉功能并不是很强大,比如:对行键中间连续几位进行一段区间式的查询,好似默认的比较器是无能为力的,只能采用自定义比较器实现(或许个人水平有限,未能发觉,如有不对,欢迎指正)。网上资料不多,过程一波三折.........,记之

 

1、搭建Protocol Buffers环境

使用过滤器执行查询时,比较器会被从执行的客户端传输到Hbase的服务端,最终在RegionServer上运行比较器的比较方法过滤的数据。而比较器从客户端传输到服务端,使用的序列化协议既不是json也不是xml,而是谷哥的protobuf!!!  (1M内的文本效率极高 !)

 

1.1、下载protobuf-2.5.0解压,windows下额外下载protoc-2.5.0-win32,解压后将protoc.exe 放在protobuf-2.5.0的src目录下。

1.2、接着配置环境变量Path

Hbase自定义比较器_第1张图片

 

cmd窗口使用protoc查看版本成功即可。

 

2、创建proto文件,使用protoc命令生成java代码

 

例:TimestampBitProtos.proto
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


// This file contains protocol buffers that are used for filters


option java_package = "com.sky.cy.protos";	    //生成java代码的包名
option java_outer_classname = "TimestampBitProtos"; //生成的类名
option java_generic_services = true;
option java_generate_equals_and_hash = true;
option optimize_for = SPEED;


// This file contains protocol buffers that are used for comparators (e.g. in filters)

message TimestampBitComparator {
  required int32  skip=1;//自定义比较器中需序列化的字段
  required string data=2;//自定义比较器中需序列化的字段
}
	    //生成java代码的包名
option java_outer_classname = "TimestampBitProtos"; //生成的类名
option java_generic_services = true;
option java_generate_equals_and_hash = true;
option optimize_for = SPEED;


// This file contains protocol buffers that are used for comparators (e.g. in filters)

message TimestampBitComparator {
  required int32  skip=1;//自定义比较器中需序列化的字段
  required string data=2;//自定义比较器中需序列化的字段
}

cmd窗口中命令生成java代码 

 

 

命令:protoc.exe -I=D:/proto --java_out=D:/proto D:/proto/TimestampBitProtos.proto

 

自定义比较器的序列化类生成完毕!

如图:

Hbase自定义比较器_第2张图片

 

3、创建比较器类,继承ByteArrayComparable,重写toByteArray、compareTo、parseFrom方法

 

import com.google.protobuf.InvalidProtocolBufferException;
import com.sky.cy.protos.TimestampBitProtos;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.util.Bytes;

/**
 * @描述: 自定义比较器
 * @文件名: TimestampComparator.java
 * @创建人: wangxinxin
 * @创建时间: 2018/3/9
 * @修改人: wangxinxin
 * @修改备注: 
*

*/ public class TimestampComparator extends ByteArrayComparable { public static final Log LOG = LogFactory.getLog(TimestampComparator.class); private byte[] data; //跳过字节数 private int skip; public TimestampComparator(byte[] data) { super(data); this.data = data; } /** * @param data 目标时间戳 * @param skip 跳过字节数 */ public TimestampComparator(byte[] data, int skip) { super(data); this.data = data; this.skip = skip; } @Override public byte[] toByteArray() { TimestampBitProtos.TimestampBitComparator.Builder builder = TimestampBitProtos.TimestampBitComparator.newBuilder(); builder.setData(Bytes.toString(this.data)); builder.setSkip(this.skip); return builder.build().toByteArray(); } public static TimestampComparator parseFrom(byte[] pbBytes) throws DeserializationException { TimestampBitProtos.TimestampBitComparator prop = null; try { prop = TimestampBitProtos.TimestampBitComparator.parseFrom(pbBytes); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } return new TimestampComparator(Bytes.toBytes(prop.getData()), prop.getSkip()); } @Override public int compareTo(byte[] bytes, int offset, int len) { if (len < 13) { return 1; } else { /*byte转为long比较*/ /*long timeTarget = Long.parseLong(new String(data)); long timeInDB = Long.parseLong(new String(bytes, skip + offset, 13)); if (timeTarget < timeInDB) { return -1; } else if (timeTarget == timeInDB) { return 0; } else { return 1; }*/ for (int i = 0; i < data.length; i++) { byte b1 = data[i]; byte b2 = bytes[i + offset + skip]; if (b1 < b2) { return -1; } else if (b1 > b2) { return 1; } } return 0; } } }

 

按照自己的逻辑实现compareTo方法,比较器的比较逻辑所在。

使用protobuf生成的java类实现toByteArray方法,用于比较器的序列化。

使用protobuf生成的java类实现parseFrom方法,在RegionServer上反序列化使用。

自定义比较器类创建完毕!

 

4、将实现的自定义的比较器打包,放入Hbase的各RegionServer的lib目录下

不然使用自定义比较器会出现ClassNotFound错误。

 

(如有不对,欢迎指正!)

 

---------------------------------补充分割线2019年10月14日----------------------------

如今想来,当初想利用Hbase比较器实现复杂条件的查询的想法,貌似是错误的!

Hbase作为NoSql库,自身拥有高可扩展性,rowkey查询的高性能等特性,而复杂的业务条件,组合查询应该使用外部索引去实现更为妥当!(ES、Solr)

你可能感兴趣的:(大数据,Hbase)