一、调用RPC框架:Caller和Callable
主要对象用途
caller主要是进行rpc的重复尝试调用;
callable由caller来调用,负责寻找目标regionserver以及进行rpc调用。
流程图
说明
1、hbase客户端的rpc调用框架主要通过RpcRetryingCaller来调用,它的核心方法callwithRetires()会尝试一定次数直到成功或超时。
2、callWithRetires()中的核心是调用RegionServerCallable的prepare()和call()方法。
prepare:获得目标regionserver的HRegionLocation(在缓存中获取,缓存中找不到则从hbase:meta中定位寻找),以及进行rpc交互的客户端stub。
call:进行probuf的rpc调用。
二、hdfs上的文件结构
hbase:meta数据
通过hbase hfile -p -f /user/hbase/data/hbase/meta/1588230740/info/4308912b2ee74a37be992667d3f3ffbe 可以查看hfile中的值
device有几个region就会在device下出现多条,device后的名称是device,startRow,建表时间戳.MD5(device,startRow,建表时间戳)中的MD5值
例:
device,,1386514885394.fcd218f786702d8660a707e96d04ca94
device,551086096,1386514885394.3d48139a0840cc6aa349988bc05b4416
各表在hdfs中的位置
hbase:meta : /user/hbase/data/hbase/meta/
其他表:/user/hbase/data/default下,以device表为例(/user/hbase/data/default/device/)看其hdfs文件路径:
三、get/scan client源码
主要对象说明
HTable: 负责表的get、scan操作。初始化时会创建HConnection对象以及缓存一些hbase:meta中的记录(默认10条)
HConnection/HConnectionManager.HConnectionImplementation:负责定位目标row对应的region(HRegionLocation对象)、缓存rpc stub、缓存相应表的region信息以及与zookeeper、与regionserver建立rpc交互。
HRegionLocation: region对象,包括了region信息(HRegionInfo)以及regionserver服务器信息(ServerName)。
ZookeeperRegistry:与zookeeper进行交互,主要获得hbase:meta的相关信息(meta表所在的regionserver)。
ResultScanner/ClientScanner: client端进行Scan操作的主要对象,其会创建Caller进行rpc调用(该调用中的callable是ScannerCallable)。
ScannerCallable:RegionServerCallable的子类,其call方法中有三个动作:打开scanner、获得数据、关闭scanner。
client get代码
源码流程
说明
1、创建HTable对象时会创建HConnectionImplementation对象,其中初始化了zookeeperRegitry专门用于与zookeeper进行交互。
2、HTable.finishSetup():判断目标表是否存在以及预先缓存hbase:meta表中的一些HRegionLocation记录。
3、HConnection.locateRegion()用于定位目标表的HRegionLocation记录。其中会调用:
a、HConnetion.locateRegionInMeta()用于非meta表,即在hbase:meta表中定位目标表的HRegionLocation记录。
b、HConnection.registry.getMetaRegionLoaction()用于定位hbase:meta的HReionLocation,从而创建ClientService与habse:meta所在的regionserver进行rpc交互。
4、prefetchRegionCache()预获取hbase:meta中的记录的操作中需要加锁,防止多个线程重复获取。预获取缓存过程是通过MetaScanner来实现的。
5、MetaScanner会先通过getRowOrBefore()尝试获得一条目标表的记录来判断目标表region记录是否存在,再进行scan操作获得相应记录(默认10条)。
6、scan操作主要通过ScannerCallable来实现。每次scan时都会与regionserver进行交互:
a、打开scanner实始化scannerId。在openScanner()时服务器会保存存key=scannerId, value=RegionScannerHolder的Map,在查询时只要根据scannerId就可以得到对应的InternalScanner以及Region。
b、rpc ScanRequest操作获得相应记录,在ClientScanner.next()时调用,next()方法第一次调用时获得数据并缓存,以后调用next时只从缓存中取数据。
c、关闭该次scanner
7、ClientScanner的next()在缓存无数据时,如果ClientScanner未关闭(即currentRegion的endKey非空或者未达到stopRow),还会使用ScannerCallable进行下一轮scan。否则scan操作就结束。
8、HTable创建完成后,就开始调用HTable.get/scan方法(scan方法使用的是前面的ClientScanner逻辑)。get方法中就直接调用caller来进行rpc,其中调用callable的prepare()时,会从创建HTable时预先得到的region缓存中获得HRegionLocation,如果找不到的话就会重新去loateRegion。
HRegionLocation缓存
Map<TableName, SoftValueSortedMap<byte[], HRegionLocation>> cachedRegionLocations: 即<tableName,<startKey, HRegionLocation>>
四、读server端
HRegionServer上的get操作最终也会转化成Scan操作。而Scan的操作主要使用Hbase上的各种scanner(相当于迭代器)。hbase返回的结果会按KeyValue从小到大的顺序返回。
Scanner类图
scanner说明
scanner可分成四类:
1、InternalScanner: 可以认为是scanner的scanner,其每个元素都有子scanner。如RegionScanner中有StoreScanner,StoreScanner中有KeyValueScanner。
2、KeyValueScanner: 用于访问KeyValue值,主要是MemStoreScanner访问MemStore中的KeyValue和StoreFileScanner访问StoreFile中的KeyValue。
查询时由于目标数据还在memstore中未flush到storefile中 或已经多次flush到多个storefile,所以这些都是Scanner的目标。
3、KeyValueHeap: 保存了KeyValueScanner的优先队列。
4、HFileScanner: 访问HFile。
其中InternalScanner的next方法是next(List<Cell> result), 而KeyValueScanner的next方法没有参数,直接返回KeyValue。
next方法是获取数据并往后移,peek方法是获取数据但不往后移。
get/scan源码过程
说明
1、scanner初始化过程
a、在Scan过程中先创建RegionScanner对象,其中会创建其familyColumn下的各个StoreScanner并存在RegionScanner的storeHeap中。
b、StoreScanner在初始化时会分别从MemStore和StoreFile中获得Scanner并存到StoreScanner.heap中。其中的selectScannersFrom()方法会调用KeyValueScanner.shouldUseScanner()进行bloom filter(只针对storefile)、time range、memOnly、filesOnly等过滤。
2、scanner遍历过程
a、起点:RegionScanner.next(),会调用其storeHeap.next方法即得到StoreScanner
b、StoreScanner.next()会循环调用其heap.next()获得相应的KeyValueScanner,并调用MemStoreScanner/StoreFileScanner的next()方法。
优先级队列中scanner的大小比较规则
1、KeyValue的大小比较规则,优先级从大到小依次为RowKey cf+cq timestamp type, 除了ts是降序外,其他都是升序。比如说,在比较2个KeyValue时,先比较RowKey的大小('a' < 'b'),相同的情况下比较cf+cq的大小('cf1:q1'<'cf2:q1'<'cf2:q2'),如果还是相同的话就比较时间戳(3042211081<3042211080,注意 时间戳的long值越大,表示数据越新,在从小到大的队列中越靠前),如果上述仍然还相同则比较TYPE('DeleteFamily' < 'DeleteColumn' < 'Delete' < Put)
2、KeyValueScanner的大小比较规则:其大小有peek()即第一个元素(即最小的)获取到KeyValue大小决定,即 KeyValueScanner1.peek() < KeyValueScanner2.peek() 则KeyValueScanner1 < KeyValueScanner2
优先队列KeyValueHeap.next(List<Cell> result):InternalScanner.next(List<Cell> result)
优先队列KeyValueHeap.next():KeyValueScanner.next()
KeyValueScanner.next说明
1、优先队列的初始化:
a、在添加storefile前会根据timestamp,columns,bloomfilter过滤掉一部分。同时,storefile中最大的rowkey比当前查询的rowkey小的记录也会被过滤。
b、storefile的内部有三维有序的,但是各个storefile之间并不是有序的。比如,storefile1中可能有rowkey为100到110的记录,而storefile2可能有rowkey为105到115的数据,所以storefile之间的rowkey的范围很有可能有交叉,所以查询数据的过程也不可能是对storefile的顺序查找。hbase采用的是优先队列方式来存储,其排序算法是根据上面的KeyValueScanner从小到大的顺序进行排序。
2、查询(以KeyValueScanner都是storefile为例,MemStoreScanner和其一样的规则):
a、获取数据。通过poll取出队列的头storefile,会从storefile读取一条记录返回。
b、决定下一条要scanner的KeyValue。当前storefile的下条记录并不一定是查询结果的下一条记录,因为队列的比较顺序是比较的每个storefile的第一条符合要求的KeyValue。所以,hbase会继续从队列中剩下的storefile取第一条记录,把该记录与当前storefile的第二条记录做比较,如果前者大,那么返回当前storefile的第二条记录;如果后者大,则会把当前storefile放回队列重新排序,在重新取队列的头storefile。然后重复上面的整个过程。
3、举例:表device,有两个storefile,storefile1中包括rowkey100,rowkey110;storefile2中包括rowkey104,rowkey108。 执行scan ‘device′扫描表device中的所有的记录。
根据前面提到的排序规则,队列中会有2个元素,按顺序分别为storefile1,storefile2。
a、取出storefile1中的第一条记录rowkey100,并返回该结果
b、取出storefile1中的下一条记录rowkey110,同时取出队列剩余storefile的第一条记录rowkey104,经过比较rowkey110大于rowkey104,则将storefile1放回队列中
c、因为队列是有序的队列,会重新对storefile进行排序,因为此时storefile1的最小rowkey为110,而storefile2的最小rowkey为104,所以排序的结果为storefile2,storefile1
d、重复上面的过程,直到查不到记录为止。
最后查到的结果为:rowkey100,rowkey104,rowkey108,rowkey110。
BlockCache:从storefile中获得相应KeyValue时会先从BlockCache中查看是否有该数据,有则在BlockCache中获得数据,否则就得去查询HFile数据。
MemStore以及StoreFile以及HFile这几块还未深入研究,待更新...
note:图片请右键在新页面打开
相关推荐
HBase源码分析与开发实战视频技术讲解高阶视频教程以及课件,内部讲解资料 内容非常详细 值得想要提高薪水的人去学习了解
HBase源码分析揭示了HBase在RPC通信机制方面的一些关键技术点,这包括了角色分配、通信信道建立、通信接口协议定义、对象序列化、传输控制和会话管理,以及在传输过程中可能出现的错误处理和重试机制。 HBase中的...
这个“hbase-0.96 jar包”是HBase 0.96版本的二进制发行版,它包含了运行和开发HBase应用所需的所有库文件。HBase 0.96是一个重要的里程碑,因为它在性能和稳定性上都有显著提升,特别是在处理大规模数据集时。 ...
源码分析是理解HBase工作原理和技术细节的重要途径。HBase在大数据领域扮演着关键角色,它能够处理海量数据并提供实时访问。下面,我们将深入探讨HBase的核心概念和源码中的关键组件。 1. **HBase架构**:HBase基于...
HBase 0.96版本是一个较早但仍然重要的发行版,它引入了许多功能和改进,使得处理大规模数据变得更加高效。下面我们将深入探讨HBase 0.96版本中的关键Java编程知识点。 首先,理解HBase的基础架构至关重要。HBase是...
该项目为基于Java开发的分布式NoSQL数据库HBase的设计源码,包含5289个文件,涵盖各类编程语言和文件类型,其中Java源文件4465个,Ruby脚本221个,XML配置112个,Protobuf定义66个,以及少量Shell、Python、...
HBase 0.96则是基于Hadoop的数据库,设计为高度可扩展的列式数据库,适用于实时查询。 **Hadoop 2.6的伪分布式安装** 在伪分布式模式下,所有的Hadoop组件都运行在一个单一节点上,这对于测试和学习Hadoop的环境...
HBase的源码分析有助于理解其内部工作原理。例如,`HRegionServer`是数据服务的主要组件,负责Region的管理和数据操作;`HMaster`负责Region的分配和负载均衡;`HStore`管理Column Family,包含一系列的`HStoreFile...
源码包“hbase-0.98.1-src.tar.gz”提供了HBase 0.98.1版本的完整源代码,对于理解其内部工作原理、进行二次开发或调试是非常有价值的。 HBase的核心概念包括: 1. 表:HBase中的表由行和列族组成,表名全局唯一。...
在Java中操作HBase,尤其是基于0.96版本的新API,涉及到许多核心概念和方法。HBase是一个分布式的、可扩展的列式数据库,它建立在Hadoop之上,适用于实时读写大数据。本篇文章将深入探讨如何使用Java API与HBase进行...
本使用kafka,spark,hbase开发日志分析系统。 ![architecture](/docs/images/architecture.png "architecture") ### 软件模块 * Kafka:作为日志事件的消息系统,具有分布式,可分区,可冗余的消息服务功能。...
通过分析和实践《HBase权威指南》的源码,读者不仅可以深化理论知识,还能掌握实际操作技巧,为解决实际项目中的问题提供有力支持。对于想深入理解HBase工作原理和优化技巧的开发者来说,这份源码是一份宝贵的资源。
Hadoop2.2+Zookeeper3.4.5+HBase0.96集群环境搭建 Hadoop2.2+Zookeeper3.4.5+HBase0.96集群环境搭建是大数据处理和存储的重要组件,本文档将指导用户从零开始搭建一个完整的Hadoop2.2+Zookeeper3.4.5+HBase0.96集群...
在Java编程环境中,操作HBase并将其数据写入HDFS(Hadoop Distributed File System)是一项常见的任务,特别是在大数据处理和分析的场景下。本篇将详细介绍如何使用Java API实现这一功能,以及涉及到的关键技术和...
### HBase源码分析 #### 一、HBase性能测试要点与分析 ##### 1.1 测试环境 - **硬件配置**: - 客户端:1台 - RegionServer:5台 - Master:1台 - ZooKeeper:3台 - **软件配置**: - CPU:每台服务器配备8...
HBase 1.2.0是该数据库的一个稳定版本,包含了众多优化和改进,对于想要深入理解HBase工作原理或者进行大数据分析的学习者来说,研究其源码是非常有价值的。 一、HBase架构与核心概念 1. 表与Region:HBase中的...
HBase 0.94.4的源码分析有助于我们深入了解其内部机制,从而更好地进行系统设计和优化。无论是对于开发者还是管理员,掌握HBase的核心原理都将极大地提升在大数据领域的实践能力。通过不断学习和实践,我们可以更好...
### HBase性能深度分析 HBase,作为BigTable的一个开源实现,因其卓越的分布式数据库特性在大数据处理领域占据了重要地位。然而,随着HBase在各行业的广泛应用,用户对其性能表现的关注日益增强,尤其是实时数据...