摘要:  大家在使用HBase和Solr搭建系统中经常遇到的一个问题就是:“我通过SOLR得到了RowKeys后,该怎样去HBase上取数据”。使用现有的Filter性能差劲,网上也没有现成的自定义Filter解决方案,我在这里把这个问题的解决办法分享给大家,抛砖引玉一下。先讲一下,虽然使用自定义过滤器来达到取数据的目的,但它其实并不是一个好的解决办法,因为它的性能是有问题的,具体分析还要看我的博客HBase 高性能获取数据 - 多线程批量式解决办法http://www.cnblogs.com/wgp13x/p/4245182.html


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了吗?Comparision Filters,Dedicated Filters,Decorating Filters,可以或可以且,可以相等,还可以组合,看起来很丰满,用起来很骨感。经过一番实践过后,性能低得吓人,使用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;

}

 
        经过验证,在MySQL单表数量为1000万时,过滤主键300个ID共花费20s左右;在HBase单表数据量达到1000万条时,过滤300条RowKey的数据共花了10多秒,显然此Filter的性能比自带Filter的性能提高了不少,还要优于MySQL主键获取,但我觉得尚且不够,性能还远远达不到目标要求。这种方式肯定不能达到高速度取数据的目的,高性能方法还要看我最新的博客:HBase 高性能获取数据 - 多线程批量式解决办法http://www.cnblogs.com/wgp13x/p/4245182.html
 
        另,有挂靠《系统集成项目管理师》的公司吗?我刚考过,有需要的Q我详聊。写在2014年末。
 

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

  1. HBase 高性能获取数据(多线程批量式解决办法) + MySQL和HBase性能测试比较

    摘要:   在前篇博客里已经讲述了通过一个自定义 HBase Filter来获取数据的办法,在末尾指出此办法的性能是不能满足应用要求的,很显然对于如此成熟的HBase来说,高性能获取数据应该不是问题. ...

  2. Hbase之尝试使用错误列族获取数据

    import com.google.common.base.Strings; import org.apache.hadoop.conf.Configuration; import org.apach ...

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

    摘要:如何从HBase中的海量数据中,以很快的速度的获取大批量数据,这一议题已经在<HBase 高性能获取数据>(http://www.cnblogs.com/wgp13x/p/42451 ...

  4. hbase高性能读取数据

    有时需要从hbase中一次读取大量的数据,同时对实时性有较高的要求.可以从两方面进行考虑:1.hbase提供的get方法提供了批量获取数据方法,通过组装一个list<Get> gets即可 ...

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

    在ios实际开发当中,我们常常用到Core Data做为数据储存首选.但在处理一些大量复杂的数据值且数据之间相互关联的时候,这就不得不使用关系型数据库来实现.例如一个导航程序,自身应该包含大量的地图自 ...

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

    1 过滤器HBase 的基本 API,包括增.删.改.查等.增.删都是相对简单的操作,与传统的 RDBMS 相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根据行键的范围来查询( ...

  7. HBase Filter 过滤器之 Comparator 原理及源码学习

    前言:上篇文章HBase Filter 过滤器概述对HBase过滤器的组成及其家谱进行简单介绍,本篇文章主要对HBase过滤器之比较器作一个补充介绍,也算是HBase Filter学习的必备低阶魂技吧 ...

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

    一.系统过滤器使用说明 1.OutputCache过滤器 OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数.它有以下属性: Duration :缓存的时间, 以 ...

  9. HBase filter shell操作

    创建表 create 'test1', 'lf', 'sf' lf: column family of LONG values (binary value) -- sf: column family ...

随机推荐

  1. 【转】Python中的GIL、多进程和多线程

    转自:http://lesliezhu.github.io/public/2015-04-20-python-multi-process-thread.html 目录 1. GIL(Global In ...

  2. ASP.NET运行时详解 生命周期入口分析

    说起ASP.NET的生命周期,网上有很多的介绍.之前也看了些这方面的博客,但我感觉很多程序猿像我一样,看的时候似乎明白,一段时间过后又忘了.所以,最近Heavi花了一段时间研究ASP.NET的源代码, ...

  3. C# LLSQL快速查询框架

    介绍一种新类型查询方法,类似linq,lambda语法,类似标准的sql使用习惯,支持匿名类型,泛型,目前支持mssql,mysql, 切换只需要DatabaseConfig.DatabaseType ...

  4. C#中dategridview数据导出为excel文件

    先从数据库中获取数据,绑定在datagridview中,再从dategridview中导出为excel文件 1.新建窗体,把控件datagridview和按钮设置好,如图

  5. knockout的依赖属性dependentObservable和observable的监控的使用

    1.Knockout是在下面三个核心功能是建立起来的:监控属性(Observables)和依赖跟踪(Dependency tracking) 声明式绑定(Declarative bindings) 模 ...

  6. windows下react-native环境搭建

    首先不得不先吐槽一下自己,一个坑总是踩很多次,且乐此不疲. 咋办? 写博客记录记录呗. 零.记录的点 Java环境的下载与配置 Android环境的下载与配置 Node环境的下载与配置 创建第一个re ...

  7. 【Effective Java】2、构造参数过多的时候

    package cn.xf.cp.ch02.item2; /** * * 功能:当我们的构造参数有很多,超出可控范围的时候,用build模式 时间:下午8:25:05 文件:NutritionFact ...

  8. NYOJ 1058 部分和问题

    部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K.   输入 首先, ...

  9. 【GOF23设计模式】责任链模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_责任链模式.公文审批.供应链系统的采购审批.异常链.过滤器和拦截器调用过程 package com.test.chainO ...

  10. [Xamarin.Android] Support Library Tips

    [Xamarin.Android] Support Library Tips Support Library支持内容 Xamarin Support Library每个版本支持.那些组件,可以参考这份 ...