大数据技术之一条数据的HBase之旅
沉沙 2019-03-13 来源 : 阅读 892 评论 0

摘要:本篇文章探讨了大数据技术之一条数据的HBase之旅,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

本篇文章探讨了大数据技术之一条数据的HBase之旅,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

大数据技术之一条数据的HBase之旅

  示例数据

  给出一份我们日常都可以接触到的数据样例,先简单给出示例数据的字段定义:

  示例数据字段定义

  本文力求简洁,仅给出了最简单的几个字段定义。如下是”虚构”的样例数据:

  示例数据

  在本文大部分内容中所涉及的一条数据,是上面加粗的最后一行"Mobile1"为"13400006666"这行记录。在下面的流程图中,我们使用下面这样一个红色小图标来表示该数据所在的位置:

  数据位置标记

  可选接口

  HBase中提供了如下几种主要的接口:

  Java Client API

  HBase的基础API,应用最为广泛。

  HBase Shell

  基于Shell的命令行操作接口,基于Java Client API实现。

  Restful API

  Rest Server侧基于Java Client API实现。

  Thrift API

  Thrift Server侧基于Java Client API实现。

  MapReduce Based Batch Manipulation API

  基于MapReduce的批量数据读写API。

  除了上述主要的API,HBase还提供了基于Spark的批量操作接口以及C++ Client接口,但这两个特性都被规划在了3.0版本中,当前尚在开发中。

  无论是HBase Shell/Restful API还是Thrift API,都是基于Java Client API实现的。因此,接下来关于流程的介绍,都是基于Java Client API的调用流程展开的。

  关于表服务接口的抽象

  同步连接与异步连接,分别提供了不同的表服务接口抽象:

  Table 同步连接中的表服务接口定义

  AsyncTable 异步连接中的表服务接口定义

  异步连接AsyncConnection获取AsyncTable实例的接口默认实现:

  Create AsyncTable

  同步连接ClusterConnection的实现类ConnectionImplementation中获取Table实例的接口实现:

  Create Table

  写数据的几种方式

  Single Put

  单条记录单条记录的随机put操作。Single Put所对应的接口定义如下:

  在AsyncTable接口中的定义:

  CompletableFuture<Void> put(Put put);

  在Table接口中的定义:

  void put(Put put) throws IOException;

  Batch Put

  汇聚了几十条甚至是几百上千条记录之后的小批次随机put操作。

  Batch Put只是本文对该类型操作的称法,实际的接口名称如下所示:

  在AsyncTable接口中的定义:

  List<CompletableFuture<Void>> put(List<Put> puts);

  在Table接口中的定义:

  void put(List<Put> puts) throws IOException;

  Bulkload

  基于MapReduce API提供的数据批量导入能力,导入数据量通常在GB级别以上,Bulkload能够绕过Java Client API直接生成HBase的底层数据文件(HFile)。

  构建Put对象

  设计合理的RowKey

  RowKey通常是一个或若干个字段的直接组合或经一定处理后的信息,因为一个表中所有的数据都是基于RowKey排序的,RowKey的设计对读写都会有直接的性能影响。

  我们基于本文的样例数据,先给出两种RowKey的设计,并简单讨论各自的优缺点:

  样例数据:

  示例数据

  RowKey Format 1: Mobile1 + StartTime

  为了方便读者理解,我们在两个字段之间添加了连接符”^”。如下是RowKey以及相关排序结果:

  RowKey Format 1

  RowKey Format 2: StartTime + Mobile1

  RowKey Format 2

  从上面两个表格可以看出来,不同的字段组合顺序设计,带来截然不同的排序结果,我们将RowKey中的第一个字段称之为“先导字段”。第一种设计,有利于查询”手机号码XXX的在某时间范围内的数据记录”,但不利于查询”某段时间范围内有哪些手机号码拨出了电话?”,而第二种设计却恰好相反。

  上面是两种设计都是两个字段的直接组合,这种设计在实际应用中,会带来读写热点问题,难以保障数据读写请求在所有Regions之间的负载均衡。避免热点的常见方法有如下几种:

  Reversing

  如果先导字段本身会带来热点问题,但该字段尾部的信息却具备良好的随机性,此时,可以考虑将先导字段做反转处理,将尾部几位直接提前到前面,或者直接将整个字段完全反转。

  将先导字段Mobile1翻转后,就具备非常好的随机性。

  例如:

  13400001111^201803010800

  将先导字段Mobile1反转后的RowKey变为:

  11110000431^201803010800

  Salting

  Salting的原理是在RowKey的前面添加固定长度的随机Bytes,随机Bytes能保障数据在所有Regions间的负载均衡。

  RowKey With Salting

  Salting能很好的保障写入时将数据均匀分散到各个Region中,但对于读取却是不友好的,例如,如果读取Mobile1为”13400001111″在20180301这一天的数据记录时,因为Salting Bytes信息是随机选择添加的,查询时并不知道前面添加的Salting Bytes是”A”,因此{“A”, “B”, “C”}所关联的Regions都得去查看一下。

  Hashing

  Hashing是将一个RowKey通过一个Hash函数生成一组固定长度的bytes,Hash函数能保障所生成的随机bytes具备良好的离散度,从而也能够均匀打散到各个Region中。Hashing既有利于随机写入,又利于基于知道RowKey各字段的确切信息之后的随机读取操作,但如果是基于RowKey范围的Scan或者是RowKey的模糊信息进行查询的话,就会带来显著的性能问题,因为原来在字典顺序相邻的RowKey列表,通过Hashing打散后导致这些数据被分散到了多个Region中。

  因此,RowKey的设计,需要充分考虑业务的读写特点。

  本文内容假设RowKey设计:reversing(Mobile1) +StartTime

  也就是说,RowKey由反转处理后的Mobile1与StartTime组成。对于我们所关注的这行数据:

  关注的数据记录

  RowKey应该为: 66660000431^201803011300

  因为创建表时预设的Region与RowKey强相关,我们现在才可以给出本文样例所需要创建的表的”Region分割点“信息:

  假设,Region分割点为“1,2,3,4,5,6,7,8,9”,基于这9个分割点,可以预先创建10个Region,这10个Region的StartKey和StopKey如下所示:

  Region划分信息

  第一个Region的StartKey为空,最后一个Region的StopKey为空

  每一个Region区间,都包含StartKey本身,但不包含StopKey

  由于Mobile1字段的最后一位是0~9之间的随机数字,因此,可以均匀打散到这10个Region中

  定义列

  每一个列在HBase中体现为一个KeyValue,而每一个KeyValue拥有特定的组成结构。

  所谓的定义列,就是需要定义出每一个列要存放的列族(Column Family)以及列标识(Qualifier)信息。

  我们假设,存放样例数据的这个表名称为”TelRecords” ,为了简单起见,仅仅设置了1个名为”I”的列族。

  Column Family以及列标识定义

  因为Mobile1与StartTime都已经被包含在RowKey中,所以,不需要再在列中存储一份。关于列族名称与列标识名称,建议应该简短一些,因为这些信息都会被包含在KeyValue里面,过长的名称会导致数据膨胀。

  基于RowKey和列定义信息,就可以组建HBase的Put对象,一个Put对象用来描述待写入的一行数据,一个Put可以理解成与某个RowKey关联的1个或多个KeyValue的集合。

  至此,这条数据已经转变成了Put对象,如下图所示:

  Put

  数据路由

  初始化ZooKeeper Session

  因为meta Region存放于ZooKeeper中,在第一次从ZooKeeper中读取META Region的地址时,需要先初始化一个ZooKeeper Session。ZooKeeper Session是ZooKeeper Client与ZooKeeper Server端所建立的一个会话,通过心跳机制保持长连接。

  获取Region路由信息

  通过前面建立的连接,从ZooKeeper中读取meta Region所在的RegionServer,这个读取流程,当前已经是异步的。获取了meta Region的路由信息以后,再从meta Region中定位要读写的RowKey所关联的Region信息。如下图所示:

  Region Routing

  因为每一个用户表Region都是一个RowKey Range,meta Region中记录了每一个用户表Region的路由以及状态信息,以RegionName(包含表名,Region StartKey,Region ID,副本ID等信息)作为RowKey。基于一条用户数据RowKey,快速查询该RowKey所属的Region的方法其实很简单:只需要基于表名以及该用户数据RowKey,构建一个虚拟的Region Key,然后通过Reverse Scan的方式,读到的第一条Region记录就是该数据所关联的Region。如下图所示:

  Location User Region

  Region只要不被迁移,那么获取的该Region的路由信息就是一直有效的,因此,HBase Client有一个Cache机制来缓存Region的路由信息,避免每次读写都要去访问ZooKeeper或者meta Region。


本文由职坐标整理发布,学习更多的相关知识,请关注职坐标IT知识库!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程