HBase中的Client如何路由到正确的RegionServer
在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer。什么叫相应的RegionServer?就是管理你要操作的那个Region的RegionServer。Client本身并不知道哪个RegionServer管理哪个Region,那么它是如何找到相应的RegionServer的?本文就是在研究源码的基础上揭秘这个过程。
在前面的文章“HBase存储架构”中我们已经讨论了HBase基本的存储架构。在此基础上我们引入两个特殊的概念:-ROOT-和.META.。这是什么?它们是HBase的两张内置表,从存储结构和操作方法的角度来说,它们和其他HBase的表没有任何区别,你可以认为这就是两张普通的表,对于普通表的操作对它们都适用。它们与众不同的地方是HBase用它们来存贮一个重要的系统信息——Region的分布情况以及每个Region的详细信息。
好了,既然我们前面说到-ROOT-和.META.可以被看作是两张普通的表,那么它们和其他表一样就应该有自己的表结构。没错,它们有自己的表结构,并且这两张表的表结构是相同的,在分析源码之后我将这个表结构大致的画了出来:
我们来仔细分析一下这个结构,每条Row记录了一个Region的信息。
首先是RowKey,RowKey由三部分组成:TableName, StartKey 和 TimeStamp。RowKey存储的内容我们又称之为Region的Name。哦,还记得吗?我们在前面的文章中提到的,用来存放Region的文件夹的名字是RegionName的Hash值,因为RegionName可能包含某些非法字符。现在你应该知道为什么RegionName会包含非法字符了吧,因为StartKey是被允许包含任何值的。将组成RowKey的三个部分用逗号连接就构成了整个RowKey,这里TimeStamp使用十进制的数字字符串来表示的。这里有一个RowKey的例子:
Table1,RK10000,12345678
然后是表中最主要的Family:info,info里面包含三个Column:regioninfo, server, serverstartcode。其中regioninfo就是Region的详细信息,包括StartKey, EndKey 以及每个Family的信息等等。server存储的就是管理这个Region的RegionServer的地址。
所以当Region被拆分、合并或者重新分配的时候,都需要来修改这张表的内容。
到目前为止我们已经学习了必须的背景知识,下面我们要正式开始介绍Client端寻找RegionServer的整个过程。我打算用一个假想的例子来学习这个过程,因此我先构建了假想的-ROOT-表和.META.表。
我们先来看.META.表,假设HBase中只有两张用户表:Table1和Table2,Table1非常大,被划分成了很多Region,因此在.META.表中有很多条Row用来记录这些Region。而Table2很小,只是被划分成了两个Region,因此在.META.中只有两条Row用来记录。这个表的内容看上去是这个样子的:
.META.
现在假设我们要从Table2里面插寻一条RowKey是RK10000的数据。那么我们应该遵循以下步骤:
1. 从.META.表里面查询哪个Region包含这条数据。
2. 获取管理这个Region的RegionServer地址。
3. 连接这个RegionServer, 查到这条数据。
好,我们先来第一步。问题是.META.也是一张普通的表,我们需要先知道哪个RegionServer管理了.META.表,怎么办?有一个方法,我们把管理.META.表的RegionServer的地址放到ZooKeeper上面不久行了,这样大家都知道了谁在管理.META.。
貌似问题解决了,但对于这个例子我们遇到了一个新问题。因为Table1实在太大了,它的Region实在太多了,.META.为了存储这些Region信息,花费了大量的空间,自己也需要划分成多个Region。这就意味着可能有多个RegionServer在管理.META.。怎么办?在ZooKeeper里面存储所有管理.META.的RegionServer地址让Client自己去遍历?HBase并不是这么做的。
HBase的做法是用另外一个表来记录.META.的Region信息,就和.META.记录用户表的Region信息一模一样。这个表就是-ROOT-表。这也解释了为什么-ROOT-和.META.拥有相同的表结构,因为他们的原理是一模一样的。
假设.META.表被分成了两个Region,那么-ROOT-的内容看上去大概是这个样子的:
-ROOT-
这么一来Client端就需要先去访问-ROOT-表。所以需要知道管理-ROOT-表的RegionServer的地址。这个地址被存在ZooKeeper中。默认的路径是:
/hbase/root-region-server
等等,如果-ROOT-表太大了,要被分成多个Region怎么办?嘿嘿,HBase认为-ROOT-表不会大到那个程度,因此-ROOT-只会有一个Region,这个Region的信息也是被存在HBase内部的。
现在让我们从头来过,我们要查询Table2中RowKey是RK10000的数据。整个路由过程的主要代码在org.apache.hadoop.hbase.client.HConnectionManager.TableServers中:
private HRegionLocation locateRegion(final byte [] tableName,
final byte [] row, boolean useCache)
throws IOException{
if (tableName == null || tableName.length == 0) {
throw new IllegalArgumentException(
“table name cannot be null or zero length”);
}
if (Bytes.equals(tableName, ROOT_TABLE_NAME)) {
synchronized (rootRegionLock) {
// This block guards against two threads trying to find the root
// region at the same time. One will go do the find while the
// second waits. The second thread will not do find.
if (!useCache || rootRegionLocation == null) {
this.rootRegionLocation = locateRootRegion();
}
return this.rootRegionLocation;
}
} else if (Bytes.equals(tableName, META_TABLE_NAME)) {
return locateRegionInMeta(ROOT_TABLE_NAME, tableName, row, useCache,
metaRegionLock);
} else {
// Region not in the cache – have to go to the meta RS
return locateRegionInMeta(META_TABLE_NAME, tableName, row, useCache, userRegionLock);
}
}
这是一个递归调用的过程:
获取Table2,RowKey为RK10000的RegionServer
=>
获取.META.,RowKey为Table2,RK10000, 99999999999999的RegionServer
=>
获取-ROOT-,RowKey为.META.,Table2,RK10000,99999999999999,99999999999999的RegionServer
=>
获取-ROOT-的RegionServer
=>
从ZooKeeper得到-ROOT-的RegionServer
=>
从-ROOT-表中查到RowKey最接近(小于)
.META.,Table2,RK10000,99999999999999,99999999999999的一条Row,并得到.META.的RegionServer
=>
从.META.表中查到RowKey最接近(小于)Table2,RK10000, 99999999999999的一条Row,并得到Table2的RegionServer
=>
从Table2中查到RK10000的Row
到此为止Client完成了路由RegionServer的整个过程,在整个过程中使用了添加“99999999999999”后缀并查找最接近(小于)RowKey的方法。对于这个方法大家可以仔细揣摩一下,并不是很难理解。
最后要提醒大家注意两件事情:
- 在整个路由过程中并没有涉及到MasterServer,也就是说HBase日常的数据操作并不需要MasterServer,不会造成MasterServer的负担。
- Client端并不会每次数据操作都做这整个路由过程,很多数据都会被Cache起来。至于如何Cache,则不在本文的讨论范围之内。
HBase中的Client如何路由到正确的RegionServer的更多相关文章
- client 如何找到正确的RegionServer(HBase -ROOT-和.META.表)
在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...
- 【转】HBase中Zookeeper,RegionServer,Master,Client之间关系
在2.0之前HDFS中只有一个NameNode,但对于在线的应用只有一个NameNode是不安全的,故在2.0中对NameNode进行抽象,抽象成NamService其下包含有多个NameNode,但 ...
- java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中
1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...
- 处理ASP.NET Core中的HTML5客户端路由回退
在使用由Angular,React,Vue等应用程序框架构建的客户端应用程序时,您总是会处理HTML5客户端路由,它将完全在浏览器中处理到页面和组件的客户端路由.几乎完全在浏览器中... HTML5客 ...
- Hbase总结(八)Hbase中的Coprocessor
1.起因(Why HBase Coprocessor) HBase作为列族数据库最常常被人诟病的特性包含:无法轻易建立"二级索引",难以运行求和.计数.排序等操作.比方,在旧版本 ...
- 使用bulkload向hbase中批量写入数据
1.数据样式 写入之前,需要整理以下数据的格式,之后将数据保存到hdfs中,本例使用的样式如下(用tab分开): row1 N row2 M row3 B row4 V row5 N row6 M r ...
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- 简单通过java的socket&serversocket以及多线程技术实现多客户端的数据的传输,并将数据写入hbase中
业务需求说明,由于公司数据中心处于刚开始部署的阶段,这需要涉及其它部分将数据全部汇总到数据中心,这实现的方式是同上传json文件,通过采用socket&serversocket实现传输. 其中 ...
- HBase中的备份和故障恢复方法
本文将对Apache HBase可用的数据备份机制和大量数据的故障恢复/容灾机制做简要介绍. 随着HBase在重要的商业系统中应用的大量添加,很多企业须要通过对它们的HBase集群建立健壮的备份和故障 ...
随机推荐
- 部署weblogic 12c的几点收获
最近刚编写完weblogic12c的部署脚本,这里将过程中的几点收获进行记录: 1.windows下编写的脚本在linux环境下运行需要dos2unix进行格式转换 2.weblogic安装环境检测需 ...
- Photon3Unity3D.dll 解析四——LitePeer
LitePeer 玩家 Connect 连接服务器 Disconnect 断开与服务器的连接 OpJoin 进入游戏 OpLeave 离开游戏,但仍与服务器保持连接 ...
- Shell语言系列之一:文件处理
前言   标准输入/输出可能是软件工具设计原则里最基本的观念了.有很多UNIX程序都遵循这一设计历练.默认情况下,他们会读取标准输入,写入标准输出,并将错误信息传递给标准错误输出. & ...
- ceph rgw java sdk 使用域名访问服务时需要设置s3client的配置项 PathStyleAccess 为true, 负责将报域名异常
Caused by: java.net.UnknownHostException: my-new-bucket.s3.yyclouds.com at java.net.InetAddress.getA ...
- 前端canvas合并图片两种实现方式
---恢复内容开始--- 需求: 有一个固定的背景图,还有一个是随机生成的二维码,合并成一张图,让用户下载. 实现一:纯手写,这里为了省事生成图片我直接给的base64,其实使用qrcode.js生成 ...
- HTML5 Canvas 初探
仅仅只是一个简单的hello world. js代码很简单: <!DOCTYPE HTML> <html lang="cn"> <head> & ...
- socket.io分布式
socket.io是目前较为流行的web实时推送框架,其基于nodejs语言开发,底层用engine.io实现. 借助nodejs语言异步的特性,其获得了不错的性能.但单个实例的socket.io依然 ...
- React篇章-React 组件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...
- 2018IEEE冬季生物识别学校 5天课程
里边有很多介绍及相关报告的PPT https://www.comp.hkbu.edu.hk/wsb18/index.php https://www.comp.hkbu.edu.hk/wsb18/pro ...
- 【JAVAWEB学习笔记】网上商城实战4:订单模块
今日任务 完成订单模块的功能 1.1 订单 模块的功能 1.1.1 我的订单: [我的订单的查询] * 在header.jsp中点击我的订单. * 提交到Servlet: * 获得用户 ...