# Hbase读数据流程

# 参考

  1. 图解HBase读取流程-Nosql漫谈 (opens new window)
  2. HBase原理-数据读取流程解析 (opens new window)
  3. HBase原理-迟到的‘数据读取流程’部分细节 (opens new window)
  4. 一条数据的HBase之旅,简明HBase入门教程-Write全流程-Nosql漫谈 (opens new window)

# HBase原理-数据读取流程解析

#

查询比较复杂,一是因为整个HBase存储引擎基于LSM-Like树实现 其二是因为HBase中更新操作以及删除操作实现都很简单,更新操作并没有更新原有数据 是插入了一条打上”deleted”标签的数据,而真正的数据删除发生在系统异步执行Major_Compact的时候 但是对于数据读取来说却意味着套上了层层枷锁

image

image

客户端缓存RegionServer地址信息

scan数据就和开发商盖房一样,也是分成两步:组建施工队体系,明确每个工人的职责;一层一层盖楼。

scanner体系的核心在于三层scanner:RegionScanner、StoreScanner以及StoreFileScanner。三者是层级的关系,一个RegionScanner由多个StoreScanner构成,一张表由多个列族组成,就有多少个StoreScanner负责该列族的数据扫描。一个StoreScanner又是由多个StoreFileScanner组成。每个Store的数据由内存中的MemStore和磁盘上的StoreFile文件组成,相对应的,StoreScanner对象会雇佣一个MemStoreScanner和N个StoreFileScanner来进行实际的数据读取,每个StoreFile文件对应一个StoreFileScanner,注意:StoreFileScanner和MemstoreScanner是整个scan的最终执行者。

image

HBase中KeyValue是什么样的结构?

image

# 图解HBase读取流程-Nosql漫谈

image

image

每一个MemStore中可能涉及一个Active Segment,以及一个或多个Immutable Segments

image

image

HFile由Block构成,默认地,用户数据被按序组织成一个个64KB的Block

基于一个给定的RowKey,HFile中提供的索引信息能够快速查询到对应的Data Block

image

# 读命题

如何从1个或多个列族(1个或多个MemStore Segments+1个或多个HFiles)所构成的Region中读取用户所期望的数据?这些数据默认必须是未被标记删除的、未过期的而且是最新版本的数据。

# 将Get看作一类特殊的Scan

可以将Get看作是一种特殊的Scan,只不过它的StartRow与StopRow重叠,事实上,RegionServer侧处理Get请求时的确先将Get先转换成了一个Scan操作。

# Scan操作各种Scanner

  • 关于一个Region的读取,被封装成一个RegionScanner对象。
  • 每一个Store/Column Family的读取操作,被封装在一个StoreScanner对象中。
  • SegmentScanner与StoreFileScanner分别用来描述关于MemStore中的Segment以及HFile的读取操作。
  • StoreFileScanner中关于HFile的实际读取操作,由HFileScanner完成。

image

image

每一个Scanner内部有一个指针指向当前要读取的KeyValue,KeyValueHeap的核心是一个优先级队列(PriorityQueue)在这个PriorityQueue中,按照每一个Scanner当前指针所指向的KeyValue进行排序

同样的,RegionScanner中的多个StoreScanner,也被组织在一个KeyValueHeap对象中:

image

# Scanner体系

KeyValueScanner定义了读取KeyValue的基础接口:

image

实现了KeyValueScanner接口类的主要Scanner包括:

  • StoreFileScanner
  • SegmentScanner
  • StoreScanner

# Scanner初始化

image

通过next请求获取一个个keyvalue

image

每一个Scanner中都有一个current指针指向下一个即将要读取的KeyValue,KeyValueHeap中的PriorityQueue正是按照每一个Scanner的current所指向的KeyValue进行排序

下一次next请求,将会返回ScannerB中的KeyValue.....周而复始,直到某一个Scanner所读取的数据耗尽,该Scanner将会被close,不再出现在上面的PriorityQueue中。

# 多个版本

image

# 如某次Scan在允许读多个版本的同时,限定了只读取C1~C3

image

# 最普通的Scan

image

# Scanner基础能力

如果只需要当前列的最新版本,那么Scanner应该可以跳过当前列的其它版本,而且将指针移到下一列的开始位置。

如果当前行的所要读取的列都已读完,那么,Scanner应该可以跳过该行剩余的列,将指针移动到下一行的开始位置。

# 如何决策跳转

ScanQueryMatcher

INCLUDE_AND_SEEK_NEXT_ROW

包含当前KeyValue,并提示Scanner当前行已无需继续读取,请Seek到下一行。

INCLUDE_AND_SEEK_NEXT_COL

包含当前KeyValue,并提示Scanner当前列已无需继续读取,请Seek到下一列。