这里面说的read既包括get,也包括scan,实际底层来看这两个操作也是一样的。
我们将要讨论的是,当我们从一张表读取数据的时候hbase到底是怎么处理的。
分二种情况来看,第一种就是表刚创建,所有put的数据还在memstore中,并没有刷新到hdfs上;第二种情况是,该store已经进行多次的flush操作,产生了多个storefile了。
在具体说明两种情况前,先考虑下表的region的问题,如果表只有一个region,那么没有说的,肯定是要扫描这个唯一的region。假设该表有多个region,此时.META.表就派上用场了,hbase会首先根据你要扫描的数据的rowkey来判断到底该数据放在哪个region上,该region所在服务器地址,然后把数据读取的请求发送给该region server。好了,实际对数据访问的任务都会放在region server上执行,为了简单起见,接下来的讨论都是在单台region server上对单个region的操作。
首先来看第一种情况,表刚创建,所有put的数据还在memstore中,并没有刷新到hdfs上。这个时候数据是在memstore中,并没有storefile产生,理所当然,hbase要查找memstore来获得相应的数据。对于memstore或者storefile来说,内存中都有关于rowkey的索引的,所以对于通过rowkey的查询速度是非常快速的。通过查询该索引就知道是否存在需要查看的数据,已经该数据在memstore中的位置。通过索引提供的信息就很容易找得到所需要的数据。这种情况很简单。
在来看第二种情况,该store已经进行多次的flush操作,产生了多个storefile了。那么数据应该从哪里查呢?所有的storefile?别忘记还有memstore。此时memstore中可能还会有没来得及flush的数据呢。如果此时该region还有很多的文件,是不是所有的文件都需要查找呢?hbase在查找先会根据时间戳或者查询列的信息来进行过滤,过滤掉那些肯定不含有所需数据的storefile或者memstore,尽量把我们的查询目标范围缩小。
尽管缩小了,但仍可能会有多个文件需要扫描的。storefile的内部有三维有序的,但是各个storefile之间并不是有序的。比如,storefile1中可能有rowkey为100到110的记录,而storefile2可能有rowkey为105到115的数据,storefile的rowkey的范围很有可能有交叉。所以查询数据的过程也不可能是对storefile的顺序查找。
hbase会首先查看每个storefile的最小的rowkey,然后按照从小到大的顺序进行排序,结果放到一个队列中,排序的算法就是按照hbase的三维顺序,按照rowkey,column,ts进行排序,rowkey和column是升序,而ts是降序。
实际上并不是所有满足时间戳和列过滤的文件都会加到这个队列中,hbase会首先对各个storefile中的数据进行探测,只会扫描扫描那些存在比当前查询的rowkey大的记录的storefile。举例来说,我当前要查找的rowkey为108,storefile1中rowkey范围为100~104,storefile2中rowkey的范围为105~110,那么对于storefile1最大的rowkey为104,小于105,所以不存在比所查rowkey105大的记录,storefile并不会被加到该队列中。根据相同的规则,storefile2则会被添加到该队列中。
队列有了,下面开始查询数据,首先通过poll取出队列的头storefile,会从storefile读取一条记录返回;接下来呢,该storefile的下条记录并不一定是查询结果的下一条记录,因为队列的比较顺序是比较的每个storefile的第一条符合要求的rowkey。所以,hbase会继续从队列中剩下的storefile取第一条记录,把该记录与头storefile的第二条记录做比较,如果前者大,那么返回头storefile的第二条记录;如果后者大,则会把头storefile放回队列重新排序,在重新取队列的头storefile。然后重复上面的整个过程。这个过程比较烦,语言描述不清楚,代码会更加清晰。
这段代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public KeyValue next()  throws IOException {
  if(this.current == null) {
    return null;
  }
  KeyValue kvReturn = this.current.next();
  KeyValue kvNext = this.current.peek();
  if (kvNext == null) {
    this.current.close();
    this.current = this.heap.poll();
  } else {
    KeyValueScanner topScanner = this.heap.peek();
    if (topScanner == null ||
        this.comparator.compare(kvNext, topScanner.peek()) >= 0) {
      this.heap.add(this.current);
      this.current = this.heap.poll();
    }
  }
  return kvReturn;
}

以上的代码在KeyValueHeap.java类中。
举个例子来说明:表sunwg01,有两个storefile,storefile1中包括rowkey100,rowkey110;storefile2中包括rowkey104,rowkey108。我现在执行scan ‘sunwg01′扫描表sunwg01中的所有的记录。
根据前面提到的排序规则,队列中会有2个元素,按顺序分别为storefile1,storefile2。
1,取出storefile1中的第一条记录rowkey100,并返回该结果
2,取出storefile1中的下一条记录rowkey110,同时取出队列剩余storefile的第一条记录rowkey104,经过比较rowkey110大于rowkey104,则将storefile1放回队列中
3,因为队列是有序的队列,会重新对storefile进行排序,因为此时storefile1的最小rowkey为110,而storefile2的最小rowkey为104,所以排序的结果为storefile2,storefile1
4,重复上面的过程,直到查不到记录为止。
最后查到的结果为:rowkey100,rowkey104,rowkey108,rowkey110。
顺便说下block cache的事情,当从storefile中读数据的时候会首先查看block cache中是否有该数据,如果有则直接查block cache,就没必要查询hdfs;如果没有该数据,那么就只能去查hdfs了。这也是为了block cache的命中率对性能有很大影响的原因。
上面描述了从hbase中read的基本的过程,还有些细节没有具体说,但是大概过程应该是都说到了。

关于hbase的read操作的深入研究 region到storefile过程的更多相关文章

  1. Hbase优化:(待重点研究)

    一.服务端调优 1.参数配置 1).hbase.regionserver.handler.count:该设置决定了处理RPC的线程数量,默认值是10,通常可以调大,比如:150,当请求内容很大(上MB ...

  2. hadoop执行hdfs文件到hbase表插入操作(xjl456852原创)

    本例中需要将hdfs上的文本文件,解析后插入到hbase的表中. 本例用到的hadoop版本2.7.2 hbase版本1.2.2 hbase的表如下: create 'ns2:user', 'info ...

  3. hbase的常用的shell命令&hbase的DDL操作&hbase的DML操作

    前言 笔者在分类中的hbase栏目之前已经分享了hbase的安装以及一些常用的shell命令的使用,这里不仅仅重新复习一下shell命令,还会介绍hbase的DDL以及DML的相关操作. hbase的 ...

  4. Hbase_02、Hbase的常用的shell命令&Hbase的DDL操作&Hbase的DML操作(转)

    阅读目录 前言 一.hbase的shell操作 1.1启动hbase shell 1.2执行hbase shell的帮助文档 1.3退出hbase shell 1.4使用status命令查看hbase ...

  5. Hbase理论&&hbase shell&&python操作hbase&&python通过mapreduce操作hbase

    一.Hbase搭建: 二.理论知识介绍: 1Hbase介绍: Hbase是分布式.面向列的开源数据库(其实准确的说是面向列族).HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hb ...

  6. HBase(2) Java 操作 HBase 教程

    目录 一.简介 二.hbase-client 引入 三.连接操作 四.表操作 五.运行测试 FAQ 参考文档 一.简介 在上一篇文章 HBase 基础入门 中,我们已经介绍了 HBase 的一些基本概 ...

  7. Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作

    Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作 1.sparkstreaming实时写入Hbase(saveAsNewAPIHadoopDataset方法 ...

  8. hbase日常运维管用命令,region管理

    1         Hbase日常运维 1.1       监控Hbase运行状况 1.1.1        操作系统 1.1.1.1 IO 群集网络IO,磁盘IO,HDFS IO IO越大说明文件读 ...

  9. 使用Django.core.cache操作Memcached导致性能不稳定的分析过程

    使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...

随机推荐

  1. 关于 Code First

    第一感觉还是很新鲜的,你可以自由的控制数据结构. 比如,你想象oracle那样,给每个表增加4个字段,创建人,创建时间,更新人,更新时间.完全可以创建一个父类包含着四个属性(甚至可以把四个属性作为一个 ...

  2. Category的使用

    1.创建一个objective-c file , 可以选择 category, extension ,protocol, empty 文件.选category 就能建立类别. category机制,它 ...

  3. 适配6 、6P 来源互联网

    iPhone 6 6P出现后,如何将一份设计稿支持多个尺寸? 如何只出一套iOS平台设计稿?随着苹果发布两种新尺寸的大屏iPhone 6,下面三款iPhone尺寸和分辨率数据就知道屏幕有多杂了. 现在 ...

  4. Good Sentences

    Wine in, truth out One is never too old to learn What is done can not be undone Time tries all thing ...

  5. sikuli实例

    代码: package selenium.sikuli; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; im ...

  6. weblogic诊断案例-AdminServer平均1-2周崩溃

    OS2台:RH5.5 64位 WEBLOGIC VERSION:9.2.3 JDK:1.5 64位 weblogic一个管理服务,4个受管(2台服务器做集群,每台服务器2个受管).应用部署后通过一个月 ...

  7. Hibernate注解:一对多外键关联

    情形:两个表,cms_mode是主表,cms_model_field是子表,cms_model_field的model_id字段关联到cms_model的主键. # # Source for tabl ...

  8. poj 2240 Arbitrage bellman-ford算法

    点击打开链接 Arbitrage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13434   Accepted: 5657 ...

  9. java中的 json 处理包

    Jackson 以前很火 Fastjson 阿里巴巴出品

  10. FileZilla - Windows XP经典软件系列

    官网: https://filezilla-project.org/ 下载: http://sourceforge.net/projects/filezilla/ 版本:V3.9.0.1 (支持XP最 ...