大数据最佳实践 | HBase客户端(上)

Posted 中兴大数据

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据最佳实践 | HBase客户端(上)相关的知识,希望对你有一定的参考价值。



之前两期我们讲了HBase服务端的几项最佳实践,重点在于设计方面。接下来几期我们将讲解HBase客户端的最佳实践,主要通过代码示例的方式为大家说明。




1.1 HBase过滤器


1.1.1问题提出


HBase中两种主要的数据读取函数是get()和scan(),它们都支持直接访问数据以及通过指定起止行键访问数据的功能。也可以在查询中添加更多的限制条件来减少查询得到的数据量,这些限制可以是指定的列族、列、时间戳以及版本号,通过这些方法可以帮助用户控制哪些数据在查询时被包含其中,但是缺少一些细粒度的筛选功能,比如基于正则表达式对行键或值进行筛选。


1.1.2解决思路


HBase Filter(过滤器)为我们提供了非常强大的特性来提高表中数据处理的效率。


常用的主要有以下过滤器:Rowfilter、FamilyDilter、QualifierFilter、ValueFilter、SingleColumnValueFilter、SingleColumnValueExcludeFilter、PrefixFilter、PageFilter、KeyOnlyFilter和FirstKeyOnlyFilter。


1.1.3实践情况


HBase提供以下过滤器的比较操作符:

操作

描述

LESS

<

LESS_OR_EQUAL

<=

EQUAL

=

NOT_EQUAL

<>

GREATER_OR_EQUAL

>=

GREATER

>

NO_OP

排除一切值


以及比较器:

比较器

描述

BinaryComparator

按字节索引顺序比较指定字节数组,采用Bytes.compareTo(byte[])

BinaryPrefixComparator

跟前面相同,只是比较左端的数据是否相同

NullComparator

判断给定的是否为空

BitComparator

按位比较 a BitwiseOp class 做异或,与,并操作

RegexStringComparator

提供一个正则的比较器,仅支持 EQUAL 和NOT_EQUAL

SubstringComparator

判断提供的子串是否出现在table的value中


接下来我们试用一下几个常用的过滤器。


1)Rowfilter过滤器,通过比较rowkey来确定选择合适的行信息。

构造函数如下:

public RowFilter(org.apache.hadoop.hbase.filter.CompareFilter.CompareOp rowCompareOp, org.apache.hadoop.hbase.filter.WritableByteArrayComparable rowComparator) {}

示例代码如下:

Scan scan = new Scan();

scan.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-0"));

// 精确匹配

Filter filter1 = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("row-22")));

scan.setFilter(filter1);

ResultScanner scanner1 = table.getScanner(scan);

System.out.println("Scanning table #1...");

for (Result res : scanner1) {

System.out.println(res);

}

scanner1.close();

// 正则匹配

Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*-.5"));

scan.setFilter(filter2);

ResultScanner scanner2 = table.getScanner(scan);

System.out.println("Scanning table #2...");

for (Result res : scanner2) {

System.out.println(res);

}

scanner2.close();

// 字串匹配

Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("-5"));

scan.setFilter(filter3);

ResultScanner scanner3 = table.getScanner(scan);

System.out.println("Scanning table #3...");

for (Result res : scanner3) {

System.out.println(res);

}

scanner3.close();


2)FamilyFilter过滤器,通过和列族名比较,返回为真的数据。

构造函数如下:

public FamilyFilter(CompareOp familyCompareOp, ByteArrayComparable familyComparator) {}

示例代码如下:

// 列族名小于指定值

Filter filter1 = new FamilyFilter(CompareFilter.CompareOp.LESS, new BinaryComparator(Bytes.toBytes("colfam3")));

Scan scan = new Scan();

scan.setFilter(filter1);

ResultScanner scanner = table.getScanner(scan);

System.out.println("Scanning table... ");

for (Result result : scanner) {

System.out.println(result);

}

scanner.close();

Get get1 = new Get(Bytes.toBytes("row-5"));

get1.setFilter(filter1);

Result result1 = table.get(get1);

System.out.println("Result of get(): " + result1);

// 列族名等于指定值

Filter filter2 = new FamilyFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("colfam3")));

Get get2 = new Get(Bytes.toBytes("row-5"));

get2.addFamily(Bytes.toBytes("colfam1"));

get2.setFilter(filter2);

Result result2 = table.get(get2);

System.out.println("Result of get(): " + result2);


3)QualifierFilter过滤器,通过和列名比较,返回为真的数据。

构造函数如下:

public QualifierFilter(CompareOp qualifierCompareOp, ByteArrayComparable qualifierComparator) {}

示例代码如下:

//列名小于或者等于指定值

Filter filter = new QualifierFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator( Bytes.toBytes("col-2")));


Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);

System.out.println("Scanning table... ");

for (Result result : scanner) {

System.out.println(result);

}

scanner.close();

Get get = new Get(Bytes.toBytes("row-5"));

get.setFilter(filter);

Result result = table.get(get);

System.out.println("Result of get(): " + result);


4)ValueFilter过滤器,通过KeyValue比较,返回为真的数据。

构造函数如下:

public ValueFilter(CompareOp valueCompareOp, ByteArrayComparable valueComparator) {}

示例代码如下:

// 字串匹配

Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(".4"));


Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);

System.out.println("Results of scan:");

for (Result result : scanner) {

for (KeyValue kv : result.raw()) {

System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue()));

}

}

scanner.close();

Get get = new Get(Bytes.toBytes("row-5"));

get.setFilter(filter);

Result result = table.get(get);

System.out.println("Result of get: ");

for (KeyValue kv : result.raw()) {

System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue()));

}


5)SingleColumnValueFilter过滤器,选定列簇和某一列,然后与列的value相比,正确的返回全部的row。

构造函数如下:

public SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOp compareOp, byte[] value) {};

public SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator) {};

示例代码如下:

// 值不匹配

SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"),

CompareFilter.CompareOp.NOT_EQUAL, new SubstringComparator("val-5"));

filter.setFilterIfMissing(true);


Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);

System.out.println("Results of scan:");

for (Result result : scanner) {

for (KeyValue kv : result.raw()) {

System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue()));

}

}

scanner.close();

Get get = new Get(Bytes.toBytes("row-6"));

get.setFilter(filter);

Result result = table.get(get);

System.out.println("Result of get: ");

for (KeyValue kv : result.raw()) {

System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue()));

}


6)SingleColumnValueExcludeFilter过滤器,和SingleColumnValueFilter相反,如果 条件相符,则不返回。


7)PrefixFilter过滤器,所有的row的实例匹配prefix的时候返回结果集合。

构造函数如下:

public PrefixFilter(byte[] prefix) {}

示例代码如下:

Filter filter = new PrefixFilter(Bytes.toBytes("row1"));

Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);


for (Result result : scanner) {

for (KeyValue kv : result.raw()) {

System.out.println("KV:" + kv + ", Value:" + Bytes.toString(kv.getValue()));

}

}

scanner.close();

Get get = new Get(Bytes.toBytes("row-5"));

get.setFilter(filter);

Result result = table.get(get);

for (KeyValue kv : result.raw()) {

System.out.println("KV:" + kv + ", Value:" + Bytes.toString(kv.getValue()));

}


8)PageFilter过滤器,页过滤,通过设置pagesize参数可以返回每一页page的数量。

构造函数如下:

public PageFilter(long pageSize) {}

示例代码如下:

finalbyte[] POSTFIX = newbyte[] { 0x00 };

Filter filter = new PageFilter(15);

byte[] lastRow = null;

int totalRows = 0;

while (true) {

Scan scan = new Scan();

scan.setFilter(filter);

if (lastRow != null) {

byte[] startRow = Bytes.add(lastRow, POSTFIX);

scan.setStartRow(startRow);

}

ResultScanner scanner = table.getScanner(scan);

int localRows = 0;

Result result;

while ((result = scanner.next()) != null) {

System.out.println(localRows++ + ":" + result);

totalRows++;

lastRow = result.getRow();

}

scanner.close();

if (localRows == 0)

break;

}

System.out.println("total rows:" + totalRows);


9)KeyOnlyFilter过滤器,只想获取data数据,而不是真实的val,可以使用这个过滤器。

构造函数如下:

public KeyOnlyFilter(boolean lenAsVal) {}

lenAsVal默认为假,表示不把val的长度作为val。否则 val的长度将作为val输出。

示例代码如下:

Filter filter = new KeyOnlyFilter(false);

Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);

for (Result result : scanner) {

for (KeyValue kv : result.raw()) {

System.out.println(kv + ":" + Bytes.toString(kv.getValue()));

}

}


10)FirstKeyOnlyFilter过滤器,在对hbase的表进行扫描的时候,如果指定了FirstKeyOnlyFilter过滤条件则仅仅会返回相同key的第一条kv。当对hbase中的表进行count,sum操作等集合操作的时候,使用FirstKeyOnlyFilter会带来性能上的提升。

构造函数如下:

public FirstKeyOnlyFilter() {}

示例代码如下:

Filter filter = new FirstKeyOnlyFilter();

Scan scan = new Scan();

scan.setFilter(filter);

ResultScanner scanner = table.getScanner(scan);

for (Result result : scanner) {

for (KeyValue kv : result.raw()) {

System.out.println(kv + ":" + Bytes.toString(kv.getValue()));

}

}



以上是关于大数据最佳实践 | HBase客户端(上)的主要内容,如果未能解决你的问题,请参考以下文章

HBase实践 | HBase TB级数据规模不停机迁移最佳实践

HBase 读流程解析与优化的最佳实践

《程序员》精选:HBase在滴滴出行的应用场景和最佳实践

开源大数据 OLAP 引擎最佳实践

HBase赠书|云HBase Thrift使用最佳实践

开源大数据 OLAP 引擎最佳实践