`
punishzhou
  • 浏览: 142674 次
社区版块
存档分类
最新评论

HBase scan的客户端分析

 
阅读更多

HBase中rowkey是索引,任何对全表的扫描或是统计都需要用到scan接口。

本文主要探讨的是客户端是如何通过scan来扫描hbase的table的。

 

主要关注几个问题:

 

1.每一个Table可能不止一个region,分布在不同的regionserver上。客户端需要找到每个region的位置并与之通信;

 

2.Hbase是以append形式把数据写进去的,无论是写还是删除只是在keyvalue上打个标签,然后put进内存而已。等到region的内存满64m以后,会flush成一个新的文件写入磁盘。真正的数据删除操作会等到执行compact时候进行;那么在compact之前,在内存或者是storfile里面就很夹杂着很多delete或put的数据,甚至会有相同的数据。如何正确地识别它们,并且高效率的读取所想要的数据,这就是一个很大的问题;

 

3.客户端的scan可以配置几个参数maxversion,batch,caching。第一个是功能性需求,第二和第三个则对于client的性能有提高,这几个参数是如何作用的;

 

4.客户端起多个线程进行scan的时候如何做到每个线程不相互影响或者说数据不会紊乱

 

5.如何在保证正确性的前提下高效地scan是最重要的

 

首先来看看一个简单的scan的客户端程序

 public static void getAllData(HTable table) throws IOException {

    Scan s = new Scan();
    s.setMaxVersions();
    s.setBatch(1000);
    ResultScanner rs = table.getScanner(s);
    for (Result r : rs) {
      for (KeyValue kv : r.raw()) {
        System.out.print("rowkey : " + new String(kv.getRow()) + "  ");
        System.out.println(new String(kv.getFamily()) + ":"
            + new String(kv.getQualifier()) + " timestamp " + kv.getTimestamp()
            + new String(kv.getValue()));
      }
    }
  }

 上面的函数即是一个简单的scan table的示例

 

调用的实现函数table.getScanner(s)

public ResultScanner getScanner(final Scan scan) throws IOException {
    ClientScanner s = new ClientScanner(scan);//new 一个ClientScanner对象
    s.initialize();// 初始化
    return s;
  }

 ClientScanner包含一个scan,以及caching。

客户端与regionserver通信一次,会找到regionserver的region,并扫描region返回一定数据。

这个数据量是由scan的Batch指定的。

而caching的作用就是通信一次找到region,调用扫描caching次,也就是说用这两个参数的话,一次通信可以返回的数据为caching*batch条。显然这会减少客户端和rs的通信量。

返回的数据时先放到客户端进行缓存的(这样也是为了提高性能)如果一次返回的数据过多的话,很有可能造成客户端的内存oom,通过batch的控制可以很好的解决这个问题。

clientScanner的初始化过程主要如下

private boolean nextScanner(int nbRows, final boolean done)
    throws IOException {
      // Close the previous scanner if it's open
      if (this.callable != null) {
        this.callable.setClose();
        getConnection().getRegionServerWithRetries(callable);
        this.callable = null;
      }
      // Where to start the next scanner
      byte [] localStartKey;
      // if we're at end of table, close and return false to stop iterating
      if (this.currentRegion != null) {
        byte [] endKey = this.currentRegion.getEndKey();
        if (endKey == null ||
            Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY) ||
            checkScanStopRow(endKey) ||
            done) {
          close();
                   return false;
        }
        localStartKey = endKey;
             } else {
        localStartKey = this.scan.getStartRow();
      }
           try {
        callable = getScannerCallable(localStartKey, nbRows);
        // Open a scanner on the region server starting at the
        // beginning of the region
        getConnection().getRegionServerWithRetries(callable);
        this.currentRegion = callable.getHRegionInfo();
      } catch (IOException e) {
        close();
        throw e;
      }
      return true;
    }

 

第一步是关闭callable,关闭的原因,我们下面会分析到

第二步确定localstartkey,当只有一个region的时候localstartkey是不用变化的,因为client是通过startkey来确定region的位置的。但是当有多个region的时候startkey就会变化。startkey是scan中的statrow,我们前面说过hbase是以rowkey作为索引的,也就是此处的startkey,通过tablename以及startrow我们可以知道第一个region的位置。

第三步就是getConnection().getRegionServerWithRetries(callable);
    这个过程包含两步:

    1.找到regionserver,并与之建立通信

    2 .如果是第一次扫描一个region的话会rpc调用regionserver的openscanner方法,构造一个Regionscanner,以后的数据查找都是使用该regionscanner来实现的,其内部结构比较复杂具体可见;然后会随机生成一个scannerId,与regionscanner一起放入map中,并把id返回给客户端。客户端拿到这个id以后,会与rs进行通信,rpc调用regionserver的next()方法,第一步就是会从map中取出其对应的regionscanner,类似一个tcp的三次握手,具体的取数据过程就是由regionscanner来负责的。

   

clientscanner重写了迭代器:

主要的一些功能是:当扫描的数据为空了,注意这里是指数据为空,并非是null,当初看代码的时候在此处纠结了很长时间。数据为空的时候,此时就认为该region已经扫描结束了,需要找第二个region并构造其regionscanner(region是有序的,以其在meta表中的顺序依次扫描)也就是调用nextscanner()方法。

 

如果这个时候callable没有关闭的话,那么regionscanner就不会清除。regionscanner中维护的是一系列storeScanner,每个storescanner下面又有很多storefilescanner,这些会消耗很多内存。

 

此外构建新的nextscanner的时候会重置startkey,以寻找下一个region。

 

依次循环知道到达endkey位置 。。

 

本文主要分析的是客户端的机制,涉及到服务器端的都是一笔带过。

 

分享到:
评论
1 楼 di1984HIT 2014-06-11  
查询不是并行的region查询么?这么奇怪啊。

相关推荐

    hbase用于查询客户端工具

    Phoenix将SQL语句转换为HBase的Scan操作,适合那些习惯使用SQL语法的开发人员。Phoenix支持索引、连接、子查询等特性,提高了开发效率。 5. **HBAdmin**:HBAdmin是HBase的管理工具,用于执行管理任务,如创建、...

    nosql-实验三HBase管理工具和客户端.docx

    HBase 管理工具和客户端详解 HBase 是一种基于列式存储的 NoSQL 数据库,具有高性能、可扩展性强和灵活的 schema 设计等特点。在 HBase 中,有多种管理工具和客户端可以帮助用户更好地管理和操作 HBase 数据库。 ...

    simple-hbase-client:简单的 HBase 客户端

    "simple-hbase-client"项目是一个简化版的HBase客户端,旨在帮助开发者更便捷地与HBase进行交互。这个客户端是用Java编写的,因此熟悉Java编程是使用它的前提。 首先,了解HBase的基本概念是必要的。HBase将数据...

    最新版linux hbase-2.3.2-client-bin.tar.gz

    这个客户端库包含了连接HBase集群、执行Get、Put、Scan等操作所需的API。 1. 连接集群:首先,我们需要配置HBase的连接参数,如Zookeeper地址。通过`Configuration`类可以设置这些参数,并创建`Connection`对象,以...

    hbase的表结构及客户端依赖.zip

    1. HBase客户端库:为了与HBase服务器通信,客户端需要导入HBase的客户端库。这个库包含了连接管理、RPC协议、表操作等所有必要的类和接口。 2. ZooKeeper:HBase依赖ZooKeeper进行元数据管理和服务发现。客户端...

    hbase常用JAVA API

    HBase是一种分布式、高性能、基于列族的NoSQL数据库,主要设计用于处理大规模数据存储。在Java中,我们可以使用HBase的Java API来与HBase交互,进行数据的读写操作。下面将详细介绍HBase Java API的核心概念和常用...

    hbase客户端查询工具dbeaver,dbeaver也可以同时查询多种数据库

    DBeaver提供了一个SQL编辑器,允许用户编写HBase特定的查询语句,如Get、Put、Scan等,这对于数据分析和数据提取非常有用。 4. **数据操作**:DBeaver支持对HBase数据的增删改查操作。用户可以直接在结果集面板中...

    HBase in Practise: 性能、监控和问题排查

    HBase在不同版本(1.x, 2.x, 3.0)中针对不同类型的硬件(以IO为例,HDD/SATA-SSD/PCIe-SSD/Cloud)和场景(single/batch, get/scan)做了(即将做)各种不同的优化,这些优化都有哪些?如何针对自己的生产业务和...

    hbase的java客户端api操作示例代码.zip

    在Java环境中,HBase提供了丰富的客户端API,使得开发者能够方便地进行数据的增删查改操作。本示例代码主要涵盖了以下几个核心知识点: 1. **HBase连接与配置** 在Java中操作HBase,首先需要创建一个`...

    客户端api的应用 HBtest.zip

    理解并熟练使用HBase的客户端API对于开发大数据处理应用至关重要,因为它们能够帮助开发者高效地管理、检索和分析海量数据。 总之,"客户端API的应用 HBtest.zip"提供了一个逐步学习和实践HBase客户端API的平台,...

    spring-boot-starter-hbase自定义的spring-boot的hbasestarter

    此外,`spring-boot-starter-hbase`还提供了对HBase的查询语句进行封装,比如RowKey的构造、Scan和Get操作的简化,使得查询更加直观且易于理解。例如,通过简单的API调用,就可以实现基于行键的单行查询、多行查询,...

    thrift操作Hbase数据库

    首先,我们需要在Hbase服务器上安装并配置Thrift服务,然后在客户端(这里是C#应用)中引用Thrift生成的Hbase接口库。Thrift的IDL(Interface Description Language)文件定义了与Hbase交互的协议,包括表的操作、行...

    HBase实现批量存取

    这包括HBase的客户端库、Hadoop的相关库以及Zookeeper的库。同时,还需要在项目中配置HBase的连接参数,如Zookeeper的地址和HBase的集群配置。 在实际应用中,批量操作常用于数据导入、备份、恢复等场景。例如,当...

    C#使用Thrift2操作HBase数据库

    6. **执行操作**: 通过服务代理调用HBase的API,例如`get`, `put`, `delete`, `scan`等方法,执行CRUD操作。 7. **处理结果**: 获取操作结果并处理。HBase返回的结果通常是二进制的,需要解码后才能解析为有意义的...

    HbaseGUI:Hbase图形用户界面

    提供可视化查询、元数据管理和支持预分区建表三大功能特点响应式设计Hbase数据/操作可视化提供包括Rowkey、版本号、Scan时间和各类Filter在内的高级查询提供元数据管理提供命名空间管理创建表时支持通过设置起止...

    hbasedatacompare:并发scan hbase,redis 的工具类

    Concurrent scanning of data sources 工具介绍 这是一个并发扫描数据源(hbase,redis)的工具,多线程scan提高效率,但会对机器以及集群造成一定压力。代码说明 1.concurrentRedisScan:多线程scan redis(每个线程...

    HBase使用的jar包

    1. **HBase客户端库**:这是与HBase交互的基础,包含了HBase的API,如`org.apache.hadoop.hbase.client.Connection`和`org.apache.hadoop.hbase.client.Table`等,用于创建连接、打开表、执行Get、Put、Scan等操作。...

    hbase的rowkey设计与hbase的协处理器运用.docx

    HBase 协处理器是一种高级的数据处理机制,可以对数据进行实时处理和分析。协处理器可以应用于数据清洁、数据转换、数据聚合等场景。 HBase 是一个功能强大且高性能的 NoSQL 数据库,具有广泛的应用前景。 RowKey ...

    多线程 hbase

    2. **HBase客户端API**:HBase提供了Java客户端API,支持线程安全的`HTablePool`,这个池可以管理多个`HTable`实例,每个实例对应一个HBase表,允许多线程共享和复用这些实例,减少创建和销毁HTable对象的开销。...

    CDH-Hbase的安装1

    - Zookeeper同样会为HBase创建必要的节点,可以通过Zookeeper客户端(如`zkCli.sh`)列出这些节点,确保HBase的相关节点存在。 3. **Sanity Check**: - 通过HBase Shell进行基础操作,验证HBase是否正常工作。 ...

Global site tag (gtag.js) - Google Analytics