在了解HBase架构的基础上,我们需要进一步学习HBase的读写过程,一方面是了解各个组件在整个读写过程中充当的角色,另一方面只有了解HBase的真实请求过程,才能为后续的正确使用打下初步基础,毕竟,除了会使用api,你还得知道怎么能写得更快,怎么查得更快。

1.首次读写的基本过程

在上一篇 深入HBase架构(建议收藏)中已经做了介绍。这里再重申一下。

这里要解决的主要问题是,

client如何知道去那个region server执行自己的读写请求。

有一个特殊的HBase表,叫做META table,保存了集群中各个region的位置。

而这个表的位置信息是保存在zookeeper中的。因此,当我们第一次访问HBase集群时,会做以下操作:

1)客户端从zk中获取保存meta table的位置信息,知道meta table保存在了哪个region server,并在客户端缓存这个位置信息;

2)client会查询这个保存meta table的特定的region server,查询meta table信息,在table中获取自己想要访问的row key所在的region在哪个region server上。

3)客户端直接访问目标region server,获取对应的row

这里我们需要关注一定,在读写的过程中,客户端实际上是不需要跟HMaster有任何交互的。这也是为什么我们在客户端的配置中,连接地址是填写的zookeeper的地址。

meta table信息都可以在client上进行缓存(apache的原生abase-client类的Connection的实现类中)。

2.写请求

从上文我们知道了,client如何找到目标region server发起请求。

接下来,就是正式的写操作了。

当client将写请求发送到客户端后,会执行以下流程。

(1)获取行锁: HBase中使用行锁保证对同一行数据的更新都是互斥操作,用以保证更新的原子性。

(2)Append HLog:顺序写入HLog中,并执行sync。

(3)写缓存memstore

(4)释放行锁

这里需要重点关注WAL。

WAL(Write-Ahead Logging)是一种高效、高可靠的日志机制。

基本原理就是在数据写入时,通过先顺序写入日志,然后再写入缓存,等到缓存写满之后统一落盘。

为什么可以提高写入性能和可靠性呢?

众所周知,对于磁盘的写入,顺序写性能是远高于随机写的。因此,WAL将将一次随机写转化为了一次顺序写加一次内存写,提高了性能。

至于可靠性,我们可以看到,因为先写日志再写缓存,即使发生宕机,缓存数据丢失,那么我们也可以通过恢复日志还原出丢失的数据。

另一方面,我们需要关注一下HBase中的各个结构的关系。

每个region server上只有一个HLog,但是有多个region。

每个HRegion里面有多个HStore,每个HStore会有一个写入缓存memstore,memstore是根据columnfamily来划分。

因此,在一个写入操作中,我们对任意一行的改变是落在memstore上,然后HBase并不会直接将数据落盘,而是先写入缓存,等缓存满足一定大小之后再一起落盘,生成新的HFile。

3.读请求

HBase-client上的读请求分为 两种,Get和Scan。

Get是一种随机查询的模式,根据给定的rowkey返回一行数据,虽然Get也支持输入多个rowkey返回多个结果,但是本质上是多次随机查询。具体rpc次数,看查询list的数据分布,如果都分布在一个region server上,就是一次rpc,如果是分布在3个rs,就是3次rpc,但是是并发请求和返回的,时间取决于最慢的那个。

Scan是一种批量查询的模式,根据指定的startRow和endRow进行范围扫描,获取区间内的数据。

而对于hbase服务端来说,当一个Get请求过来后,还是会转换为一个特殊的scan请求,即startrow和endrow一致的Scan请求。所以,下文的介绍,就围绕scan展开。

首先,我们要知道,HBase的写入很快,是追加多版本的形式,删除也很快,只是插入一条打上“deteled”标签的数据。因此,hbase的读操作比较复杂的,需要处理各种状态和关系。

因为Store是按照columfamily来划分的,一张表由N个列族组成,就有N个StoreScanner负责该列族的数据扫描。

当client要查询一个region,那么就会有一个RegionScanne,这个regionscannerr会创建N个StoreScanner。

而一个store由多个storefile和一个memstore组成,

因此,StoreScanner对象会创建一个MemStoreScanner和多个StoreFileScanner进行实际数据的读取。

这些scanner首先根据TimeRange和RowKey Range过滤掉一部分肯定无用的StoreFileScanner。

剩下的scanner组成一个最小堆KeyValueHeap。这个最小堆的实际数据结构是一个优先级队列,队列中所有元素是scanner,根据scanner指向的keyvalue进行排序(scanner类似游标,每次查询一个结果后,通过next下移找下一个kv值)。

举个简单的例子。

假设有4个scanner组成的优先级队列,分布标记为ScannerA\B\C\D。

1)查询的时候首先pop出heap的堆顶元素。

2)第一次pop出来的是scannerA。调用 next 请求,将会返回 ScannerA 中的 rowA:cf:colA,而后 ScannerA 的指针移动到下一个 KeyValue rowA:cf:colB;

3)重新组织堆中元素,堆中的 Scanners 排序不变;

4)第二次 pop出来的还是scannerA。调用next 请求,返回 ScannerA 中的 rowA:cf:colB,ScannerA 的 current 指针移动到下一个 KeyValue rowB:cf:ColA;

5)重新组织堆中元素,由于此时scannerA的指针指向了rowB,按照 KeyValue 排序可知 rowB 小于 rowA, 所以堆内部,scanner 顺序发生改变,改变之后如下图所示:

6)第三次pop出来的就是ScannerB了。

以此类推。

当某个scanner 内部数据完全检索之后会就会被 close 掉,或者 rowA 所有数据检索完毕,则查询下一条。

默认情况下返回的数据需要经过 ScanQueryMatcher 过滤返回的数据需要满足下面的条件:

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

至此,就是HBase大致上的读写流程。

我们经常听说HBase数据读取要读Memstore、HFile和Blockcache,为什么我们这里说Scanner只有StoreFileScanner和MemstoreScanner,而没有BlockcacheScanner呢?

因为HBase中数据仅独立地存在于Memstore和StoreFile中,Blockcache作为读缓存,里面有StoreFile中的部分热点数据,因此,如果有数据存在于Blockcache中,那么这些数据必然存在StoreFile中。因此使用MemstoreScanner和StoreFileScanner就可以覆盖到所有数据。

而在实际的读操作时,StoreFileScanner通过索引定位到待查找key所在的block之后,会先去查看该block是否存在于Blockcache中,如果存在,那么就会去BlockCache中取出,避免IO,如果BlockCache中不存在,才会再到对应的StoreFile中读取。

看到这里了,原创不易,点个关注、点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

扫码关注我的公众号“阿丸笔记”,第一时间获取最新更新。同时可以免费获取海量Java技术栈电子书、各个大厂面试题。

【从零单排HBase 03】深入HBase读写的更多相关文章

  1. 「从零单排canal 03」 canal源码分析大纲

    在前面两篇中,我们从基本概念理解了canal是一个什么项目,能应用于什么场景,然后通过一个demo体验,有了基本的体感和认识. 从这一篇开始,我们将从源码入手,深入学习canal的实现方式.了解can ...

  2. Hbase多版本的读写(Shell&Java API版)

    Hbase是基于HDFS的NOsql数据库,它很多地方跟数据库差不多,也有很多不同的地方.这里就不一一列举了,不过Hbase有个版本控制的特性,这个特性在很多场景下都会发挥很大的作用.本篇就介绍下基于 ...

  3. HBase一次客户端读写异常解读分析与优化全过程(干货)

    大数据时代,HBase作为一款扩展性极佳的分布式存储系统,越来越多地受到各种业务的青睐,以求在大数据存储的前提下实现高效的随机读写操作.对于业务方来讲,一方面关注HBase本身服务的读写性能,另一方面 ...

  4. HBase二级索引、读写流程

    HBase二级索引.读写流程 一.HBse二级索引方案 1.1 基于Coprocessor方案 1.2 Phoenix二级索引特点 1.3 Phoenix 二级索引方案 二.HBase读写流程 2.1 ...

  5. Hbase框架原理及相关的知识点理解、Hbase访问MapReduce、Hbase访问Java API、Hbase shell及Hbase性能优化总结

    转自:http://blog.csdn.net/zhongwen7710/article/details/39577431 本blog的内容包含: 第一部分:Hbase框架原理理解 第二部分:Hbas ...

  6. HBase 实战(1)--HBase的数据导入方式

    前言: 作为Hadoop生态系统中重要的一员, HBase作为分布式列式存储, 在线实时处理的特性, 备受瞩目, 将来能在很多应用场景, 取代传统关系型数据库的江湖地位. 本篇博文重点讲解HBase的 ...

  7. 4 hbase表结构 + hbase集群架构及表存储机制

      本博文的主要内容有    .hbase读取数据过程 .HBase表结构 .附带PPT http://hbase.apache.org/ 读写的时候,就需要用hbase了,换句话说,就是读写的时候. ...

  8. HBase 2、HBase安装与初试牛刀

    官方帮助文档:http://hbase.apache.org/book.html  PDF:http://hbase.apache.org/apache_hbase_reference_guide.p ...

  9. 从零单排学Redis【铂金一】

    前言 只有光头才能变强 好的,今天我们要上铂金段位了,如果还没经历过青铜和白银和黄金阶段的,可以先去蹭蹭经验再回来: 从零单排学Redis[青铜] 从零单排学Redis[白银] 从零单排学Redis[ ...

随机推荐

  1. MySQL:REPLACE函数的使用

    原文链接 REPLACE函数功能 REPLACE(columnName, search_str, replace_str) 查找columnName字段中所有search_str,并替换为replac ...

  2. JavaScript(8)--- 闭包

    JavaScript(8)--- 闭包 理解闭包 我的理解是:闭包就是能够读取其他函数内部变量的函数.由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以简单这样理解 &q ...

  3. 【面试QA-基本模型】LSTM

    目录 为什么传统 CNN 适用于 CV 任务,RNN 适用于 NLP 任务 RNN 原理 LSTM 原理 GRU 原理 RNN BPTT LSTM 如何解决 RNN 的梯度消失问题 怎样增加 LSTM ...

  4. select_related prefetch_related

    # select_related与prefetch_related# # select_related帮你直接连表操作 查询数据 括号内只能放外键字段# # res = models.Book.obj ...

  5. 第三周java实验报告

        实验三 Java基本程序设计(2) 实验时间 2018-9-13 第一部分:理论知识回顾 第一章 再次了解了java“白皮书”的关键术语,java的常见术语,对于大多数“白皮书”的关键术语依然 ...

  6. CF1326C Permutation Partitions 题解,

    原题链接 简要题意: 给定一个 \(1\) ~ \(n\) 的置换,将数组分为 \(k\) 个区间,使得每个区间的最大值之和最大.求这个值,和分区的方案数. 关键在于 \(1\) ~ \(n\) 的置 ...

  7. JDK下载、安装、卸载

    学习java的朋友,第一课就是安装JDK,如果你连他都不会安装,那就非常尴尬,如果面试的时候如果问到这个问题,就Game over了,下面来看看怎么弄吧! 了解JDK JDK的全称是JavaSE De ...

  8. shell脚本中的if条件语句介绍和使用案例

    #前言:在生产工作中if条件语句是最常使用的,如使用来判断服务状态,监控服务器的CPU,内存,磁盘等操作,所以我们需要熟悉和掌握if条件语句. #简介 if条件语句,简单来说就是:如果,那么.有if单 ...

  9. Attention-based Extraction of Structured Information from Street View Imagery:基于注意力的街景图像提取结构化信息

    基于注意力的街景图像提取结构化信息 一种用于真实图像文本提取问题的TensorFlow模型. 该文件夹包含在FSNS数据集数据集上训练新的注意OCR模型所需的代码,以在法国转录街道名称. 您还可以使用 ...

  10. LeetCode(42.接雨水)多解法详解

    接雨水解法详解: 题目: 基本思路:从图上可以看出要想接住雨水,必须是凹字形的,也就是当前位置的左右两边必须存在高度大于它的地方,所以我们要想知道当前位置最多能存储多少水,只需找到左边最高处max_l ...