在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer。什么叫相应的RegionServer?就是管理你要操作的那个Region的RegionServer。Client本身并不知道哪个RegionServer管理哪个Region,那么它是如何找到相应的RegionServer的?本文就是在研究源码的基础上揭秘这个过程。

在前面的文章“HBase存储架构”中我们已经讨论了HBase基本的存储架构。在此基础上我们引入两个特殊的概念:-ROOT-和.META.。这是什么?它们是HBase的两张内置表,从存储结构和操作方法的角度来说,它们和其他HBase的表没有任何区别,你可以认为这就是两张普通的表,对于普通表的操作对它们都适用。它们与众不同的地方是HBase用它们来存贮一个重要的系统信息——Region的分布情况以及每个Region的详细信息。

好了,既然我们前面说到-ROOT-.META.可以被看作是两张普通的表,那么它们和其他表一样就应该有自己的表结构。没错,它们有自己的表结构,并且这两张表的表结构是相同的,在分析源码之后我将这个表结构大致的画了出来:

-ROOT-和.META.表结构

我们来仔细分析一下这个结构,每条Row记录了一个Region的信息。

首先是RowKey,RowKey由三部分组成:TableName, StartKey 和 TimeStamp。RowKey存储的内容我们又称之为Region的Name。哦,还记得吗?我们在前面的文章中提到的,用来存放Region的文件夹的名字是RegionName的Hash值,因为RegionName可能包含某些非法字符。现在你应该知道为什么RegionName会包含非法字符了吧,因为StartKey是被允许包含任何值的。将组成RowKey的三个部分用逗号连接就构成了整个RowKey,这里TimeStamp使用十进制的数字字符串来表示的。这里有一个RowKey的例子:

然后是表中最主要的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中。默认的路径是:

  1. /hbase/root-region-server

等等,如果-ROOT-表太大了,要被分成多个Region怎么办?嘿嘿,HBase认为-ROOT-表不会大到那个程度,因此-ROOT-只会有一个Region,这个Region的信息也是被存在HBase内部的。

现在让我们从头来过,我们要查询Table2中RowKey是RK10000的数据。整个路由过程的主要代码在org.apache.hadoop.hbase.client.HConnectionManager.TableServers中:

  1. private HRegionLocation locateRegion(final byte[] tableName,
  2. final byte[] row, boolean useCache) throws IOException {
  3. ) {
  4. throw new IllegalArgumentException("table name cannot be null or zero length");
  5. }
  6. if (Bytes.equals(tableName, ROOT_TABLE_NAME)) {
  7. synchronized (rootRegionLock) {
  8. // This block guards against two threads trying to find the root
  9. // region at the same time. One will go do the find while the
  10. // second waits. The second thread will not do find.
  11. if (!useCache || rootRegionLocation == null) {
  12. this.rootRegionLocation = locateRootRegion();
  13. }
  14. return this.rootRegionLocation;
  15. }
  16. } else if (Bytes.equals(tableName, META_TABLE_NAME)) {
  17. return locateRegionInMeta(ROOT_TABLE_NAME, tableName, row, useCache, metaRegionLock);
  18. } else {
  19. // Region not in the cache – have to go to the meta RS
  20. return locateRegionInMeta(META_TABLE_NAME, tableName, row, useCache, userRegionLock);
  21. }
  22. }

这是一个递归调用的过程:

  1. 的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的方法。对于这个方法大家可以仔细揣摩一下,并不是很难理解。

最后要提醒大家注意两件事情:

1. 在整个路由过程中并没有涉及到MasterServer,也就是说HBase日常的数据操作并不需要MasterServer,不会造成MasterServer的负担。

2. Client端并不会每次数据操作都做这整个路由过程,很多数据都会被Cache起来。至于如何Cache,则不在本文的讨论范围之内。

HBase -ROOT-和.META.表结构(region定位原理)的更多相关文章

  1. HBase -ROOT-和.META.表结构(region定位原理) 分类: B7_HBASE 2015-03-13 20:52 90人阅读 评论(0) 收藏

    在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...

  2. HBase -ROOT-和.META.表结构

    在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...

  3. -ROOT-表和.META.表结构详解

    在<HBase技术简介>中我们知道,HBase中有两个特殊的表:-ROOT-和.META.. 由于HBase中的表可能非常大,故HBase会将表按行分成多个region,然后分配到多台Re ...

  4. client 如何找到正确的RegionServer(HBase -ROOT-和.META.表)

    在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...

  5. 【转】hbase meta表修复

    [From]https://www.iteye.com/blog/blackproof-2052898 meta表修复一 查看hbasemeta情况 hbase hbck .重新修复hbase met ...

  6. Hbase meta 表异常修复

    Hbase meta表异常修复 标签(空格分隔): Hbase 一,Hbase meta元数据表 1.1 背景 线上Hbase 因为在hbase shell中清空 truncate 'table'一张 ...

  7. hbase meta表修复

    meta表修复一 查看hbasemeta情况hbase hbck1.重新修复hbase meta表(根据hdfs上的regioninfo文件,生成meta表)hbase hbck -fixMeta2. ...

  8. hbase meta表的结构

    下面看下hbase:meta 表的结构,hbase:meta表中,保存了每个表的region地址,还有一些其他信息,例如region的名字,HRegionInfo,服务器的信息.hbase:meta表 ...

  9. HBase读写数据的详细流程及ROOT表/META表介绍

    一.HBase读数据流程 1.Client访问Zookeeper,从ZK获取-ROOT-表的位置信息,通过访问-ROOT-表获取.META.表的位置,然后确定数据所在的HRegion位置: 2.Cli ...

随机推荐

  1. php 之 类,对象(三)多态性,函数重载,克隆

    一.三大特性之三 多态性(在php中表象不明显)1.概念:当父类引用指向子类实例时,由于子类对父类函数进行了重写,导致我们在使用该引用去调用相应的方法显示出的不同.2.发生条件:1.必须有继承 2. ...

  2. 3月19日 html(一) html基础内容

    ---恢复内容开始--- 今天学习了html的第一节课,是些比较简单的基础知识,知道如何向网页里添加文本.图片.表格.超链接之类的,如何去编写这些代码. html(hyper text makeup ...

  3. win7安装memcached

    根据公司业务需求,需要用memcache缓存,正好接触一下,在win7下配置安装: 1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached 2. 在终端(也 ...

  4. python学习第十八天 --错误&异常处理

    这一章节主要讲解python的错误和异常处理 什么是错误和异常?及其区别? 错误: 1.语法错误:代码不符合解释器或者编译器语法. 2.逻辑错误:不完整或者不合法输入或者计算出现问题.   异常:执行 ...

  5. PYTHON简介及安装

    Python简介 Python是一种广泛使用的高层次,通用,解释,动态编程语言.它的设计理念强调代码的可读性,它的语法允许程序员表达更少的代码的概念比将在可能语言如C ++或Java.该语言提供旨在使 ...

  6. Android从相册中获取图片以及路径

    首先是相册图片的获取: private final String IMAGE_TYPE = "image/*"; private final int IMAGE_CODE = 0; ...

  7. MySql 学习笔记 (派生表)

    派生表也是一种子查询那么它出现在 select * from ( select * from b <--这个就是派生表啦 )派生表其实不是个好东西,在生产的时候他是可以通过索引来过滤的,但是一但 ...

  8. Codeforces 159D Palindrome pairs

    http://codeforces.com/problemset/problem/159/D 题目大意: 给出一个字符串,求取这个字符串中互相不覆盖的两个回文子串的对数. 思路:num[i]代表左端点 ...

  9. 找出最小的k个数

    •已知数组中的n个正数,找出其中最小的k个数. •例如(4.5.1.6.2.7.3.8),k=4,则最小的4个数是1,2,3,4 •要求: –高效: –分析时空效率 •扩展:能否设计出适合在海量数据中 ...

  10. 掌握 Java 8 Lambda 表达式

    Lambda 表达式 是 Java8 中最重要的功能之一.使用 Lambda 表达式 可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda 表达式 同时还提升了对 集合 ...