一个自定义 HBase Filter -“通过RowKeys来高性能获取数据”

大家在使用HBase和Solr搭建系统中经常遇到的一个问题就是:“我通过SOLR得到了RowKeys后,该怎样去HBase上取数据”。使用现有的Filter性能差劲,网上也没有现成的解决方案,我在这里把这个问题的解决办法分享给大家,抛砖引玉一下。



Solr和HBase专辑

1、“关于Solr的使用总结的心得体会”(http://www.cnblogs.com/wgp13x/p/3742653.html)

2、“中文分词器性能比较?”(http://www.cnblogs.com/wgp13x/p/3748764.html)

3、“Solr与HBase架构设计”(http://www.cnblogs.com/wgp13x/p/a8bb8ccd469c96917652201007ad3c50.html)

4、 “大数据架构: 使用HBase和Solr将存储与索引放在不同的机器上”(http://www.cnblogs.com/wgp13x/p/3927979.html)

5、“一个自定义 HBase Filter -通过RowKeys来高性能获取数据”(http://www.cnblogs.com/wgp13x/p/4196466.html)


大数据架构: 使用HBase和Solr将存储与索引放在不同的机器上”此文一经推出,览者众多,也有很多同仁朋友问我问题,看来近年关注先进大数据架构的公司越来越多了,基本上有数据接入的公司都会有这一问题。具我所知,“我该选Oracle还是MySQL作数据存储呢?”,“MySQL数据库索引创建后对双百分号%like不起作用啊!”,“没事,数据量再大我加存储柜不就行了?哈哈哈!”,这些都是还在用关系型数据库存储大数据的公司,它们往往对查询这块束手无策;它们的对策往往是:“我退而求其次,往年的数据我搜不了,我只搜今年的数据不就OK啦?反正业务单位我也能搞定。”--这是有垄断有背景的公司,也是不思进取的公司,“我分表,用户查近三个月的数据多,查前面的数据少,我每个月分一张表,解决了。”--这是吃了这顿没下顿的公司,抓紧把当前的项目搞完拿钱走人的公司,“上内存数据库哎,那个快。”--这是不管三七二十一、以屁股决定脑袋的公司。不管怎么说,能关注当前大数据架构技术的公司都是不落伍滴。

现在我把大家在使用HBase和Solr搭建系统中经常遇到的一个问题的解决办法在这里分享给大家,这个问题就是:“我通过SOLR得到了RowKeys后,该怎样去HBase上取数据”。

相信有人开始发问了,HBase不是提供了功能很强劲的Filter了吗?可以或可以且,可以相等,还可以组合,看起来很丰满,用起来很骨感。经过一番实践过后,性能低得吓人,使用200条RowKey在300百万的数据集中取数据,要等上好几钟,究其原因,多Filter的或组合过滤就是在HBase的数据里滚了一遍又一遍,不慢才怪。

那么应该怎么做呢?自定义HBase Filter,这样只要滚一遍就好啦。RowKeyFilter就是自定义的Filter,它继承自FilterBase类,类中主要定义了三个属性,byte[] value用来传入RowKeys,Map<Object, Object>用来存放传入的RowKeys,撞到了就返回,boolean filterRow用来告诉HBase是否滤掉。下面是具体的RowKeyFilter代码。


import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

import java.util.Arrays;

import java.util.HashMap;

import java.util.Map;

import org.apache.hadoop.hbase.KeyValue;

import org.apache.hadoop.hbase.filter.FilterBase;

import org.apache.hadoop.hbase.util.Bytes;

/**

* @description 自定义过滤器,用来读取大量离散行

* @author 王安琪

* @time 2014年11月8日上午10:47:17

* @className RowKeyFilter

*/

public class RowKeyFilter extends FilterBase

{

private byte[] value = null;

private boolean filterRow = true;

/**

* map中存放需要读的行RowKey

*/

public Map<Object, Object> map = new HashMap<Object, Object>();

public RowKeyFilter()

{

super();

}

public RowKeyFilter(byte[] value)

{

this.value = value;

}

@Override

public ReturnCode filterKeyValue(KeyValue ignored)

{

if (this.filterRow == false)

return ReturnCode.INCLUDE;

else

return ReturnCode.NEXT_ROW;

}

/**

* 行过滤,查询该行RowKey是否在Map中

*/

@Override

public boolean filterRowKey(byte[] buffer, int offset, int length)

{

byte[] rowKey = Arrays.copyOfRange(buffer, offset, offset + length);

String str = new String(rowKey);

if (map.containsKey(str))

{ // 在0(1)时间内返回,效率较高

this.filterRow = false; // false表示包括这一行

}

return this.filterRow;

}

@Override

public void reset()

{

this.filterRow = true;

}

@Override

public boolean filterRow()

{

return filterRow;

}

/**

* 将Map中的数据以Byte[]形式传给服务器

*/

@Override

public void write(DataOutput dataOutput) throws IOException

{

Bytes.writeByteArray(dataOutput, this.value);

}

/**

* 服务器读取Byte[]数据,再将数据存储到Map中 不同的RowKey以","分割

*/

@Override

public void readFields(DataInput dataInput) throws IOException

{

this.value = Bytes.readByteArray(dataInput);

String string = new String(this.value);

String[] strs = string.split(",");

for (String str : strs)

{

map.put(str, str);

}

}

}

自定义Filter如何加载到HBase中,网上有很多的介绍,这里就不作说明了,下面列举出了如何使用RowKeyFilter的代码段来达到筛选的目的。


/**

* 根据rowKeys获取数据

*

* @param rowKeys:每个rowkey之间使用逗号分隔符

* @param filterColumn:表示过滤的列,如果为空表示所有列的数据都返回

* @param isContiansRowkeys:设置为true,表示返回结果集中包含rowkeys;否则返回结果集中不包含rowkeys

* @return

*/

/* @Override */

public Datas getDatasFromHbase(String rowKeys, List<String> filterColumn,

boolean isContiansRowkeys)

{

Datas datas = new Datas();

HTableInterface hTableInterface = getTable(tableName);

Scan scan = new Scan();

if (filterColumn != null)

{

for (String column : filterColumn)

{

scan.addColumn(columnFamilyName.getBytes(), column.getBytes());

}

}

if (rowKeys != null && rowKeys.length() > 0)

{

RowKeyFilter rowKeyFilter = new RowKeyFilter(rowKeys.getBytes());

                        scan.setFilter(rowKeyFilter);

}

ResultScanner resultScanner = null;

List<Data> listData = new ArrayList<Data>();

try

{

resultScanner = hTableInterface.getScanner(scan);

for (Result result : resultScanner)

{

Data data = new Data();

if (isContiansRowkeys)

{

data.setRowkey(new String(result.getRow()));

}

Map<String, String> map = new HashMap<String, String>();

List<String> content = new ArrayList<String>();

String[] temp = null;

if (filterColumn != null)

{

temp = new String[filterColumn.size()];

}

for (KeyValue keyValue : result.raw())

{

if (filterColumn == null)

{

content.add(new String(keyValue.getValue()));

}

else if (filterColumn != null)

{

String qualifier = new String(keyValue.getQualifier());

String value = new String(keyValue.getValue());

if (filterColumn.contains(qualifier))

{

int index = filterColumn.indexOf(qualifier);

temp[index] = value;

}

}

}

if (temp != null)

{

for (int i = 0; i < temp.length; i++)

{

content.add(temp[i]);

}

}

data.setContent(content);

listData.add(data);

}

datas.setDatas(listData);

}

catch (IOException e)

{

e.printStackTrace();

}

finally

{

resultScanner.close();

try

{

hTableInterface.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

return datas;

}

经过验证,在HBase单表数据量达到1000万条时,过滤300条RowKey的数据共花了10多秒,显然此Filter的性能比自带Filter的性能提高了不少,但我觉得尚且不够,性能还远远达不到目标要求。不知道cnblogs的高人们有无更好的解决办法,求指教!

另,有挂靠《系统集成项目管理师》的公司吗?我刚考过,有需要的Q我详聊。写在2014年末。

http://www.cnblogs.com/wgp13x/p/4196466.html

来自王安琪

时间: 2024-10-20 23:07:39

一个自定义 HBase Filter -“通过RowKeys来高性能获取数据”的相关文章

HBase 高性能获取数据 - 多线程批量式解决办法

在前篇博客里已经讲述了通过一个自定义 HBase Filter来获取数据的办法,在末尾指出此办法的性能是不能满足应用要求的,很显然对于如此成熟的HBase来说,高性能获取数据应该不是问题.下面首先简单介绍了搜索引擎的性能,然后详细说明了HBase与MySQL的性能对比,这里的数据都是经过实际的测试获得的.最后,给出了采用多线程批量从HBase中取数据的方案,此方案经过测试要比通过自定义Filter的方式性能高出很多. Solr和HBase专辑 1.“关于Solr的使用总结的心得体会”(http:

Validform和aui2.0结合使用的表单自定义验证提示和列表页异步获取数据Demo

二.添加自定义验证演示       Validform验证提示大多都是在输入框或下拉框的右边或下面.感觉就是不美观,特别是表单字段少的时候,这种在相应对象旁边的提示就没必要了,      它会给人一种不友好的感觉(只是自己的感觉).所以下面写了三种添加演示,希望大家能给出建议,以免下次用起来纠结,不知道用哪种好.        表单验证插件是我们经常使用的Validform_v5.3.2_min.js.先上添加1演示的表单验证js代码,这里我设置了点击提交按钮后才验证.其他添加演示的区别不大,详

一个常见的elementUI表格,从后端获取数据并分页及查询

这个功能是比较常见的,初入门,把几个变量和流程搞清楚. 代码注释很清楚,方便以后优化. 前端主要代码 <template> <div class="page-container"> <!--查询工具栏--> <div class="toolbar" style="float:left;"> <el-form :inline="true" :model="appFi

HBase 高性能加入数据 - 按批多“粮仓”式解决办法

摘要:如何从HBase中的海量数据中,以很快的速度的获取大批量数据,这一议题已经在<HBase 高性能获取数据>(http://www.cnblogs.com/wgp13x/p/4245182.html)一文中给出了解决办法.那么,如何向HBase中高性能的插入数据呢?经研究表明,光是批量写入也还是不行.网上没有现成的方法.本文针对这一问题,给出了一个解决方案.它采用了多线程按批“多粮仓”的方式,经过验证,能较好的达到高速度的效果. 关键词:hbase, 高性能, 多线?程, 算法 解决问题:

Spring security3.x 自定义验证Filter

原创文章,欢迎转载!转载时务必保留:作者:jmppok ;出处http://blog.csdn.net/jmppok/article/details/44833545 1.applicationContext-secrity.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/secur

从SQLite获取数据完成一个产品信息展示

在ios实际开发当中,我们常常用到Core Data做为数据储存首选.但在处理一些大量复杂的数据值且数据之间相互关联的时候,这就不得不使用关系型数据库来实现.例如一个导航程序,自身应该包含大量的地图自身数据并且数据需要在app启动的时候就开始读取加载.而且数据本身变动不是特别频繁.重复向服务器发送请求获取信息是一件十分浪费的事情.因此我们可以用一个本地数据文件来直接配置.做为轻量级关系型数据库的sqlite是ios开发首选.而xcode本身包含了sqlite库,因此在ios使用的时候不需要额外配

HBase - Filter - 过滤器的介绍以及使用

1 过滤器HBase 的基本 API,包括增.删.改.查等.增.删都是相对简单的操作,与传统的 RDBMS 相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根据行键的范围来查询(Scan).HBase 不仅提供了这些简单的查询,而且提供了更加高级的过滤器(Filter)来查询. 1.1 过滤器的两类参数过滤器可以根据列族.列.版本等更多的条件来对数据进行过滤,基于 HBase 本身提供的三维有序(行键,列,版本有序),这些过滤器可以高效地完成查询过滤的任务,带有过滤器条件的

HBase - Filter - 过滤器的介绍以及使用 | 那伊抹微笑

博文作者:那伊抹微笑 csdn 博客地址:http://blog.csdn.net/u012185296 itdog8 地址链接 : http://www.itdog8.com/thread-214-1-1.html 博文标题:HBase - Filter - 过滤器的介绍以及使用 | 那伊抹微笑 个性签名:世界上最遥远的距离不是天涯.也不是海角.而是我站在妳的面前.妳却感觉不到我的存在 技术方向:Flume+Kafka+Storm+Redis/Hbase+Hadoop+Hive+Mahout+

asp.net MVC之 自定义过滤器(Filter) - shuaixf

一.系统过滤器使用说明 1.OutputCache过滤器 OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数.它有以下属性: Duration :缓存的时间, 以秒为单位 ,理论上缓存时间可以很长,但实际上当系统资源紧张时,缓存空间还是会被系统收回. VaryByParam :以哪个字段为标识来缓存数据,比如当"ID"字段变化时,需要改变缓存(仍可保留原来的缓存),那么应该设VaryByParam为"ID".这里你可以设置以下几