上篇博文中已经谈到,有两个流程没有讲到。一个是MetaTableAccessor.getRegionLocations,另外一个是ConnectionImplementation.cacheLocation。这一节,就让我们单独来介绍这两个流程。
首先让我们来到MetaTableAccessor.getRegionLocations。
1.调用MetaTableAccessor.getRegionInfo,获取返回结果集中指定的列信息(info:regioninfo)的值。在这个方法的调用过程中,有一个知识点需要大家关注——Result.binarySearch。我将放在后面讲解。
2.然后调用了Result.getNoVersionMap。在这里,完成了对返回结果集的含version版本信息的封装与不含version版本信息的封装,同样,我将放在后面讲解。
首先让我们来到Result.binarySearch。大家可以看到这里使用的kvs[0]的rowKey,然后使用了传入的family(info)与qualifier(regioninfo)。大家可能比较迷惑,为什么这里的逻辑是这样的。原因很简单,因为这里传入的Cell数组的rowKey都是一样的,要利用Arrays.binarySearch搜索指定family:qualifier。因此首先使用这些信息构造了一个封装了以上信息的FirstOnRowColCell。这里需要注意的是,新建的cell.getTimestamp返回值为HConstants.LATEST_TIMESTAMP = Long.MAX_VALUE。这里,大家可能会对Arrays.binarySearch的返回值比较新奇,为什么结果是负值包括后面为什么有表达式(pos = (pos+1) * -1)。大家感兴趣的可以追一下源码,我只简单说一下结论。在调用Arrays.binarySearch方法时,如果所要搜索的数组中包含键,则返回键在该数组的位置,然而,如果数组中不包含键,那么就返回-(insertion point) - 1。这里的insertion point就是该数组中第一个元素大于键的索引位置(the index of the first element greater than the key)。如果大家还是不懂,在网上搜一下就明白了,我在这里就不详述了。后面通过表达式(pos = (pos+1) * -1)也就获取的Arrays.binarySearch后的insertion point。看到这里大家可能还有点迷惑,不过,相信我在介绍完CellComparatorImpl后,大家可能就恍然大悟了。
接下来让我们来到CellComparatorImpl.compare方法。这里主要调用了compareRows与compareWithoutRow。compareRows比较简单,就是比较传入Cell的rowKey。真正重要的是compareWithoutRow。
接下来让我们来到CellComparatorImpl.compareWithoutRow方法。这里比较容易误会的是compareTimestamps。
接下来让我们来到CellComparatorImpl.compareTimestamps。正如截图中注释所说,交换顺序以实现将相同的family:qualifier按照时间戳的降序来排列(family与qualifier都是按照升序来排列的)。看到这里,相信大家就能够明白为什么构建的Cell时间戳为Long.MAX_VALUE。
不过,我还是在这里再简单介绍一下。上面我已经提到Arrays.binarySearch中insertion point是该数组中第一个元素大于键的索引位置(the index of the first element greater than the key)。假如,如果说这里的CellComparatorImpl.compareTimestamps为升序排列,那么,上面构造的key的insertion point为数组中相同family:qualifier的index + 1。而这里改为降序之后,构造的key的insertion point为数组中相同family:qualifier的index。而这个结果正是我们需要的。
到这里,大家可能就明白了Result.getColumnLatestCell方法的含义——获取指定family:qualifier中时间戳最接近Long.MAX_VALUE的cell。
接下来我插入一个知识点——Result.getMap与Result.getNoVersionMap。这里获取的是含version信息的列。通过其中的versionMap.put方法我们就可以知道,这里将不同version的value值保存在map中了。
然后来到Result.getNoVersionMap。在这里获取的是不含version的列。由于上面在构造versionMap时传入的Comparator为倒序排序,因此,这里通过qualifierEntry.getValue().firstKey()获得的是最新版本的value。
接下来,让我们来到本节中另外一个也是最后一个重要的方法ConnectionImplementation.cacheLocation。由于其主要调用了MetaCache.getCachedLocation,因此,我在这里贴出MetaCache.getCachedLocation源码,如下图所示。其中比较重要的方法是MetaCache.getTableLocations。
接下来让我们来到MetaCache.getTableLocations,如下图所示。如果看过我的上篇博文《HBase之Table.put客户端流程》,大家可能知道,我埋了一个伏笔,也就是这里的最后一个入参。上一篇中的与这里的入参类型不同,但是方法的调用流程是一样的,我就在这里详细讲解。
上图中最后一个入参是java.util.function.Supplier。如下图所示。
上图中的最后一个入参类型是Runnable。看到这里,大家可能就明白了。如果在MetaCache.cachedRegionLocations中并没有相应的key,value对,那么就会调用supplier.get方法,也就是getTableLocations的最后一个入参,重新构建一个CopyOnWriteArrayMap,并且将内部的比较器设置为Bytes.BYTES_COMPARATOR。然后将其放到MetaCache.cachedRegionLocations。
到此为止,完整的《HBase之Table.put客户端流程》就结束了。大家如果有什么疑问或者大数据相关的问题可以发送至我的邮箱15935152719@163. com。
从下一节起,也就是本周末,我将为大家带来HBase的第二章内容——Hbase之Client协议。届时,Client协议中的服务端与客户端的完整流程将为大家一一奉上。如果比较关注其中的内容可以关注我,或者成为我的粉丝,都是就可以及时收到更新啦。

转载于:https://www.cnblogs.com/letsfly/p/10067904.html

HBase之Table.put客户端流程(续)相关推荐

  1. 2021年大数据HBase(四):HBase的相关操作-客户端命令式!【建议收藏】

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 HBase的相关操作-客户端命令式 1.进入HBase ...

  2. 大数据HBase(四):HBase的相关操作-客户端命令式

    文章目录 HBase的相关操作-客户端命令式 1.进入HBase客户端命令操作界面 2.查看帮助命令

  3. 一条数据的HBase之旅,简明HBase入门教程-Write全流程

    如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,剧情才开始正式展开.本文基于提供的样例数据,介绍了写数据的接口,RowKey定义,数据在客户端的组装,数据路由,打包分发, ...

  4. hbase 使用disruptor_一条数据的HBase之旅,简明HBase入门教程-Write全流程

    如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,"剧情"才开始正式展开.本文基于所给出的样例数据,介绍了将数据从Client写到RegionServe ...

  5. HBASE ERROR: Table already exists: FileTable! list时候却查不到表

    在hbase创建表的时候报错,提示表已经存在,但是通过查询表并没有,对于这种问题的解决方式如下: 1.首先通过命令 zkCli.sh  进入到zookeeper的客户端 2.显示hbase中的表数据 ...

  6. HBase之Region上Spilt流程分析

    我们知道在MemStore达到阀值以后,会进行flushRegion操作. 那么在操作完成之后,会对HRegion进行检查,看是否HRegion是否已经达到阀值,如果已经达到阀值,则需要对HRegio ...

  7. hbase 客户端_读《HBase权威指南》 客户端API:基础知识

    HBase 的主要客户端接口是由 org.apache.hadoop.hbase.client 包中的 HTable 类提供的. 创建 HTable 实例是有代价的.每个实例都需要扫描 .META. ...

  8. HBase原理之数据读取流程

    和写流程相比,HBase读数据是一个更加复杂的操作流程,这主要基于两个方面的原因:其一是因为整个HBase存储引擎基于LSM-Like树实现,因此一次范围查询可能会涉及多个分片.多块缓存甚至多个数据存 ...

  9. 单点登录 cas 设置回调地址_cas客户端流程详解(源码解析)单点登录

    博主之前一直使用了cas客户端进行用户的单点登录操作,决定进行源码分析来看cas的整个流程,以便以后出现了问题还不知道是什么原因导致的 cas主要的形式就是通过过滤器的形式来实现的,来,贴上示例配置: ...

最新文章

  1. Spring Boot 内置Tomcat——getServletContext().getRealPath()为临时目录问题解决方案
  2. VTK:几何对象之OpenVRCone
  3. linux设置时间为24小时制,设置时区
  4. 中国长租公寓市场白皮书
  5. u盘循环冗余能修复吗_激素脸怎么办?激素脸还能改善修复好吗?
  6. 华为android出现短路怎么办,华为手机无法开机原因解析及解决方法
  7. 第三届“泰迪杯”数据分析职业技能大赛: 教育平台的线上课程智能推荐 (决赛候选)答辩PPT
  8. echarts实现省份迁徙图
  9. node的学习过程(菜鸟)
  10. 计算机组成原理 - 系统总线
  11. 会话、Cookie、Session、url重写
  12. 3月30日----4月3日二年级课程表
  13. 笔记本电脑没有WiFi选项,3个小时,我试了以下N种方法,终于出现网络了!
  14. 系统调用recvfrom和recv区别
  15. 计算机无法连接网络显示错误651,电脑连接路由器提示错误651解决办法
  16. ora-20085 ora-06512错误解决
  17. Num.01- java 之 mybatis 框架
  18. 使用tableau制作词云
  19. 微信开发生成带参数的二维码的讲解
  20. 机器学习入坑姿势之大纲

热门文章

  1. 单片机中通用的类型别名
  2. python队列只能一个个读取吗_python队列Queue的详解
  3. 【Pytorch神经网络理论篇】 30 图片分类模型:Inception模型
  4. sublime text3c语言编译运行,c – Sublime text 3 – 编译程序并在终端中运行
  5. Chapter4-1_Speech_Synthesis(Tacotron)
  6. LeetCode 732. 我的日程安排表 III(差分思想)
  7. LeetCode 1300. 转变数组后最接近目标值的数组和(二分查找)
  8. LeetCode 628. 三个数的最大乘积
  9. python槽格式里填啥_用于填充插槽的网络挂钩
  10. Python批量删除错误图片、修改文件名以及删除重复图片