HBase之读取数据流程

说明

本文参考自

HBase数据读取流程解析

hbase(二)hfile结构

目录

说明

1.HBase读取数据流程

2.疑问

2.1上述(10)中,需要对满足条件的KeyValue进行从小到大排序合并构建最小堆。

​​2.1.1为什么Scanner需要有小到大排序?

2.1.2HBase中KeyValue是什么样的结构?

2.1.3不同KeyValue之间如何进行大小比较?

2.2上述(11)中数据是如何从最小堆KeyValueHeap:PriorityQueue中一行行获取的?


1.HBase读取数据流程

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ndGFueW9uZzQ3Nzc=,size_16,color_FFFFFF,t_70

WEBRESOURCE21e60447e64693eb33226e6cce7534a6

(1)Client访问zookeeper,获取hbase:meta所在RegionServer的节点信息

(2)Client访问hbase:meta所在的RegionServer,获取hbase:meta记录的元数据后先加载到内存中,然后再从内存中根据需要查询的RowKey查询出RowKey所在的Region的相关信息(Region所在RegionServer)

(3)Client访问RowKey所在Region对应的RegionServer,发起数据读取请求

(4)RegionServer构建RegionScanner(需要查询的RowKey分布在多少个Region中就需要构建多少个RegionScanner),用于对该Region的数据检索

(5)RegionScanner构建StoreScanner(Region中有多少个Store就需要构建多少个StoreScanner,Store的数量取决于Table的ColumnFamily的数量),用于对该列族的数据检索

(6)多个StoreScanner合并构建最小堆(已排序的完全二叉树)StoreHeap:PriorityQueue<StoreScanner>

(7)StoreScanner构建一个MemStoreScanner和一个或多个StoreFileScanner(数量取决于StoreFile数量)

(8)过滤掉某些能够确定所要查询的RowKey一定不在StoreFile内的对应的StoreFileScanner或MemStoreScanner

(9)经过筛选后留下的Scanner开始做读取数据的准备,将对应的StoreFile定位到满足的RowKey的起始位置

(10)将所有的StoreFileScanner和MemStoreScanner合并构建最小堆KeyValueHeap:PriorityQueue<KeyValueScanner>,排序的规则按照KeyValue从小到大排序

(11)从KeyValueHeap:PriorityQueue<KeyValueScanner>中经过一系列筛选后一行行的得到需要查询的KeyValue。

2.疑问

2.1上述(10)中,需要对满足条件的KeyValue进行从小到大排序合并构建最小堆。

对此有三个疑问如下

  • 为什么这些Scanner需要由小到大排序?
  • HBase中KeyValue是什么样的结构?
  • 不同KeyValue之间如何进行大小比较?

​​2.1.1为什么Scanner需要有小到大排序?

最直接的解释是scan的结果需要由小到大输出给用户,当然,这并不全面,最合理的解释是只有由小到大排序才能使得scan效率最高。举个简单的例子,HBase支持数据多版本,假设用户只想获取最新版本,那只需要将这些数据由最新到最旧进行排序,然后取队首元素返回就可以。那么,如果不排序,就只能遍历所有元素,查看符不符合用户查询条件

2.1.2HBase中KeyValue是什么样的结构?

WEBRESOURCE1bf9beb9e78e5a44cc1d7cac1aa89b16

(1)KeyValue由Key length、value length、key、value组成

(2)其中key又由RowKey length、RowKey、ColumnFamily length、ColumnFamily、ColumnQualifier、TimeStamp、KeyType组成

  • RowKey length:RowKey长度
  • RowKey:RowKey内容
  • ColumnFamily length:列族长度
  • ColumnFamily:列族
  • ColumnQualifier:列名
  • Timestamp:时间戳
  • KeyType:表示类型,取值有Put/Delete/Delete Column/Delete Family

2.1.3不同KeyValue之间如何进行大小比较?

由2.1.2可知,key的内容包括RowKey、ColumnFamuly、ColumnQualifier、Timestamp、KeyType。所以keyValue的大小比较规则如下:

1.比较RowKey,RowKey越小则KeyValue越小

2.RowKey相同情况下,比较ColumnFamily,ColumnFamily越小,KeyValue越小

3.ColumnFamily相同情况下,比较ColumnQualifier,ColumnQualifier越小,KeyValue越小

4.ColumnQualifier相同情况下,比较Timestamp越大,KeyValue越小

5.Timestamp相同情况下,比较KeyType(DeleteFamily -> DeleteColumn -> Delete -> Put),KeyType级别从左到右对应的KeyValue从小到大

2.2上述(11)中数据是如何从最小堆KeyValueHeap:PriorityQueue<KeyValueScanner>中一行行获取的?

下图来自HBase数据读取流程解析

20170307203342471

这三个Scanner组成的heap为<MemstoreScanner,StoreFileScanner2, StoreFileScanner1>,Scanner由小到大排列。查询的时候首先pop出heap的堆顶元素,即MemstoreScanner,得到keyvalue = r2:cf1:name:v3:name23的数据,拿到这个keyvalue之后,需要进行如下判定:

  • 检查该KeyValue的KeyType是否是Deleted/DeletedCol等,如果是就直接忽略该列所有其他版本,跳到下列(列族)
  • 检查该KeyValue的Timestamp是否在用户设定的Timestamp Range范围,如果不在该范围,忽略
  • 检查该KeyValue是否满足用户设置的各种filter过滤器,如果不满足,忽略
  • 检查该KeyValue是否满足用户查询中设定的版本数,比如用户只查询最新版本,则忽略该cell的其他版本;反正如果用户查询所有版本,则还需要查询该cell的其他版本。

现在假设用户查询所有版本而且该keyvalue检查通过,此时当前的堆顶元素需要执行next方法去检索下一个值,并重新组织最小堆。即图中MemstoreScanner将会指向r4,重新组织最小堆之后最小堆将会变为<StoreFileScanner2, StoreFileScanner1, MemstoreScanner>,堆顶元素变为StoreFileScanner2,得到keyvalue=r2:cf1:name:v2:name22,进行一系列判定,再next,再重新组织最小堆…

不断重复这个过程,直至一行数据全部被检索得到。继续下一行…

 

 

 

 

  • 15
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值