前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HBase案例之2个逻辑思维训练小题目

HBase案例之2个逻辑思维训练小题目

作者头像
CoderJed
发布2018-09-13 10:49:39
8820
发布2018-09-13 10:49:39
举报
文章被收录于专栏:Jed的技术阶梯Jed的技术阶梯

HBase版本:hbase-1.2.6

第一题:关于rowkey的范围

现有hbase表"user"如下:

我们知道,在对Hbase表中的数据进行全表扫描时,可以指定rowkey的范围,比如:

代码语言:javascript
复制
public static void main(String[] args) throws Exception {
    Configuration conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.quorum", "192.168.21.100:2181");
    Connection conn = ConnectionFactory.createConnection(conf);
    Table table = conn.getTable(TableName.valueOf("user"));
    Scan scan = new Scan();
    scan.setStartRow(Bytes.toBytes("0001"));
    scan.setStopRow(Bytes.toBytes("0005"));
    ResultScanner scanner = table.getScanner(scan);
    HBasePrintUtil.printResultScanner(scanner);
}

这样查询出来的结果为:
0001    cf1 name    1515064512439   Jed
0002    cf1 name    1515064824770   Aiden
0003    cf1 name    1515064825023   Jacob
0004    cf1 name    1515064825025   Ethan

现在的需求是,我指定 StartRow 和 StopRow后,可以得到包括 StopRow 在内的那些行的记录,即:

代码语言:javascript
复制
0001    cf1 name    1515064512439   Jed
0002    cf1 name    1515064824770   Aiden
0003    cf1 name    1515064825023   Jacob
0004    cf1 name    1515064825025   Ethan
0005    cf1 name    1515064825034   Matthew

有这么一种想法,我要取0001-0005的记录,我写成0001-0006不就可以了吗?问题是,在大数据量的表中,你不能这么直观的看出一个rowkey的下一个rowkey是什么,例如我们这张表,0005的下一列rowkey是0005001,如果你事先不知道有这样一个rowkey的存在,把 StopRow设置为0006,那么得到结果是:

代码语言:javascript
复制
0001    cf1 name    1515064512439   Jed
0002    cf1 name    1515064824770   Aiden
0003    cf1 name    1515064825023   Jacob
0004    cf1 name    1515064825025   Ethan
0005    cf1:name    1515064825034   Matthew
0005001 cf1:name    1515064934573   value=Benjamin

这样还是没有实现我们的需求,指定 StartRow 和 StopRow后,可以得到包括 StopRow 在内的那些行的记录

实现思路:

代码:

代码语言:javascript
复制
public static void main(String[] args) throws Exception {
    Configuration conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.quorum", "192.168.21.100:2181");
    Connection conn = ConnectionFactory.createConnection(conf);
    Table table = conn.getTable(TableName.valueOf("user"));
    Scan scan = new Scan();
    scan.setStartRow(Bytes.toBytes("0001"));
    byte[] StopRow = Bytes.toBytes("0005");
    byte[] StopRowExtended = Bytes.add(StopRow, new byte[]{0X00});
    scan.setStopRow(StopRowExtended);
    ResultScanner scanner = table.getScanner(scan);
    HBasePrintUtil.printResultScanner(scanner);
}

结果:
0001    cf1 name    1515064512439   Jed
0002    cf1 name    1515064824770   Aiden
0003    cf1 name    1515064825023   Jacob
0004    cf1 name    1515064825025   Ethan
0005    cf1 name    1515064825034   Matthew

第二题:关于分页过滤器

HBase Java API 提供了分页过滤器的操作,如下

代码语言:javascript
复制
public static void main(String[] args) throws Exception {
    Configuration conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.quorum", "192.168.21.100:2181");
    Connection conn = ConnectionFactory.createConnection(conf);
    Table table = conn.getTable(TableName.valueOf("user"));
    Scan scan = new Scan();
    // 设置起始rowkey
    scan.setStartRow(Bytes.toBytes("0004"));
    // 设置每页显示3行
    Filter filter = new PageFilter(3);
    scan.setFilter(filter);
    ResultScanner scanner = table.getScanner(scan);
    HBasePrintUtil.printResultScanner(scanner);
}

结果:
0004    cf1 name    1515064825025   Ethan
0005    cf1 name    1515064825034   Matthew
0005001 cf1 name    1515064934573   Benjamin

需求是,实现一个ResultScanner getPageData(long pageIndex, long pageSize)方法,pageIndex代表起始页,pageSzie为每页显示几行,返回该页的所有数据,比如调用getPageData(3, 4),应该按照每页4行来分页,并且得到第3页的全部行。

代码:

代码语言:javascript
复制
import java.io.IOException;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.util.Bytes;

import com.aura.hbase.utils.HBasePrintUtil;

public class MyTest {
    
    public static final String ZOOKEEPER_LIST = "192.168.21.100:2181";
    public static final String TABLE_NAME = "user";
    
    public static Configuration conf = null;
    public static Table table = null;
    
    static {
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", ZOOKEEPER_LIST);
        try {
            Connection conn = ConnectionFactory.createConnection(conf);
            table = conn.getTable(TableName.valueOf(TABLE_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /*
     * 最原始的获取一页数据的方法
     */
    public static ResultScanner getPageData(String startRow, long pageSize) throws Exception {
        Scan scan = new Scan();
        Filter filter = new PageFilter(pageSize);
        if(!StringUtils.isBlank(startRow)) {
            scan.setStartRow(startRow.getBytes());
        }
        scan.setFilter(filter);
        return table.getScanner(scan);
    }

    /*
     * 把 pageIndex 转换为 startRow 的方法
     */
    public static String getStartRowByPageIndex(long pageIndex, long pageSize) throws Exception {
        String startRow = null;
        if(pageIndex > 1) {
            // 获取到某一页的最后一个 rowkey 就能加一个极小量的字节数组得到下一页的 startRow 
            for(int i = 1; i <= pageIndex-1; i++) {
                ResultScanner pageData = getPageData(startRow, pageSize);
                Result result = null;
                for(Result s : pageData) {
                    result = s;
                }
                // 当前页的最后一个 rowkey
                byte[] lastCurrentRowKey = result.getRow();
                // 下一页的 startRow
                byte[] pageFirstRowKey = Bytes.add(lastCurrentRowKey, new byte[]{0X00});
                startRow = Bytes.toString(pageFirstRowKey);
            }
        }else {
            startRow = null;
        }
        // 最后返回的就是 pageIndex 页的起始 startRow
        return startRow;
    }

    /*
     * 最终满足需求的方法
     */
    public static ResultScanner getPageData(long pageIndex, long pageSize) throws Exception {
        String startRow = getStartRowByPageIndex(pageIndex, pageSize);
        return getPageData(startRow, pageSize);
    }

    /*
     * 测试
     */
    public static void main(String[] args) throws Exception {
        HBasePrintUtil.printResultScanner(getPageData(3,4));
    }
}

结果:
0008    cf1 name    1515064825071   Joshua
0009    cf1 name    1515064825073   Michael
0010    cf1 name    1515064825075   Ryan
0011    cf1 name    1515064825078   Andrew

说明:

本文用到的HBasePrintUtil.printResultScanner()方法,请查看:

HBase Java API 01:基础操作中的HBasePrintUtil.java中的内容

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.01.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一题:关于rowkey的范围
  • 第二题:关于分页过滤器
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档