波神

导航

hadoop学习笔记(六):HBase体系结构和数据模型

1. HBase体系结构

一个完整分布式的HBase的组成示意图如下,后面我们再详细谈其工作原理。

1)Client

包含访问HBase的接口并维护cache来加快对HBase的访问。

2)Zookeeper

  • 保证任何时候,集群中只有一个master
  • 存储所有Region的寻址入口
  • 实时监控Region Server的上线和下线信息。并实时通知HMaster。
  • 存储HBase的schema和 table元数据。

3)HMaster

  • 为Region Server分配region。
  • 负责RegionServer的负载均衡(当一个 RegionServer有太多的Region,HMaster将RegionServer中的一部分HRegion移到其他的RegionServer上达到负载均衡)。
  • 发现失效的RegionServer并重新分配其上的Region。
  • 管理用户对table的增删改操作。

4)ReginServer

  • RegionServer维护Region,处理对这些Region的IO请求。(对数据的读写,首先是Client通过Zookeeper和HMaster获取RegionServer中Region的 信息,然后Client直接找到RegionServer,RegionServer对Region进行操作)
  • RegionServer负责切分在运行过程中变得过大的region(切分Region)。

5)Region(表的一部分)

  • HBase自动把表水平划分为多个Region,每个Region会保存一个表里面某段连续的数据;每个表一开始只有一个Region,随着数据不断插入表region不断增大,当达到一个阀值 的时候,region就会等分产生两个新的region(这个操作会由RegionServer完成)。
  • 当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个RegionServer上。

6)Store,MemStore和StoreFile

  • 一个Region由多个Store组成,一个Store对应一个列族。
  • Store包括位于内存中的MemStore和位于磁盘的StoreFile。当进行写操作时,首先要写入内存中的MemStore,当MemStore中的数据达到某个阀值,RegionServer会启动FlashCache进程写入StoreFile,每次写入形成单独的一个StoreFile。(MemStore有点像缓存,一次写入一次写入磁盘太过频繁,将写入缓存,当量达到一定程度,一起写入)
  • 当StoreFile文件的数量增长到一定阀值后,RegionServer会进行合并,在合并过程中会进行版本合并和删除,形成更大的StoreFile。
  • 当一个region所有StoreFile的大小和超过一定阀值后,会把当前的Region分割为两个(分割是RegionServer完成),并由HMaster分配到相应的RegionServer上,实现负载均衡。
  • 当Client检索数据时,先在MemStore找,找不到再找StoreFile。

7)总结

  • Region是HBase中分布式存储和负载均衡的最小单元。最小单元就表示不同的Region可以分布在不同的RegionServer上。
  • Region由一个或者多个Store组成,每个Store保存一个colums family(列族)。
  • 每个Store又由一个MemStore和多个StoreFile组成。 

 

2. HBase读写流程

2.1 ROOT表和META表

HBase的所有Region元数据被存储在.META.表中,随着Region的增多,.META.表中的数据也会增大,并分裂成多个新的Region。为了定位.META.表中各个Region的位置,把.META.表中所有Region的元数据保存在-ROOT-表中,最后由Zookeeper记录-ROOT-表的位置信息。所有客户端访问用户数据前,需要首先访问Zookeeper获得-ROOT-的位置,然后访问-ROOT-表获得.META.表的位置,最后根据.META.表中的信息确定用户数据存放的位置,如下图所示。

-ROOT-表永远不会被分割,它只有一个Region,这样可以保证最多只需要三次跳转就可以定位任意一个Region。为了加快访问速度,.META.表的所有Region全部保存在内存中。客户端会将查询过的位置信息缓存起来,且缓存不会主动失效。如果客户端根据缓存信息还访问不到数据,则询问相关.META.表的Region服务器,试图获取数据的位置,如果还是失败,则询问-ROOT-表相关的.META.表在哪里。最后,如果前面的信息全部失效,则通过ZooKeeper重新定位Region的信息。所以如果客户端上的缓存全部是失效,则需要进行6次网络来回,才能定位到正确的Region。

 

客户端与HBase系统的交互阶段主要有如下几个步骤:

 

  • 1.客户端首先会根据配置文件中zookeeper地址连接zookeeper,并读取/<hbase-rootdir>/meta-region-server节点信息,该节点信息存储HBase元数据(hbase:meta)表所在的RegionServer地址以及访问端口等信息。用户可以通过zookeeper命令(get /<hbase-rootdir>/meta-region-server)查看该节点信息。
  • 2.根据hbase:meta所在RegionServer的访问信息,客户端会将该元数据表加载到本地并进行缓存。然后在表中确定待检索rowkey所在的RegionServer信息。
  • 3.根据数据所在RegionServer的访问信息,客户端会向该RegionServer发送真正的数据读取请求。服务器端接收到该请求之后需要进行复杂的处理,具体的处理流程将会是这个专题的重点。


通过上述对客户端以及HBase系统的交互分析,可以基本明确两点:

  • 1.客户端只需要配置zookeeper的访问地址以及根目录,就可以进行正常的读写请求。不需要配置集群的RegionServer地址列表。
  • 2.客户端会将hbase:meta元数据表缓存在本地,因此上述步骤中前两步只会在客户端第一次请求的时候发生,之后所有请求都直接从缓存中加载元数据。如果集群发生某些变化导致hbase:meta元数据更改,客户端再根据本地元数据表请求的时候就会发生异常,此时客户端需要重新加载一份最新的元数据表到本地。

 

2.2 hbase读写流程

 

上图是RegionServer数据存储关系图。上文提到,HBase使用MemStore和StoreFile存储对表的更新。数据在更新时首先写入HLog和MemStore。MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到Flush队列,由单独的线程Flush到磁盘上,成为一个StoreFile。与此同时,系统会在Zookeeper中记录一个CheckPoint,表示这个时刻之前的数据变更已经持久化了。当系统出现意外时,可能导致MemStore中的数据丢失,此时使用HLog来恢复CheckPoint之后的数据。
StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定阈值后,就会进行一次合并操作,将对同一个key的修改合并到一起,形成一个大的StoreFile。当StoreFile的大小达到一定阈值后,又会对 StoreFile进行切分操作,等分为两个StoreFile。

2.2.1 写操作流程

  • (1) Client通过Zookeeper的调度,向RegionServer发出写数据请求,在Region中写数据。
  • (2) 数据被写入Region的MemStore,直到MemStore达到预设阈值。
  • (3) MemStore中的数据被Flush成一个StoreFile。
  • (4) 随着StoreFile文件的不断增多,当其数量增长到一定阈值后,触发Compact合并操作,将多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除。
  • (5) StoreFiles通过不断的Compact合并操作,逐步形成越来越大的StoreFile。
  • (6) 单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个新的Region。父Region会下线,新Split出的2个子Region会被HMaster分配到相应的RegionServer上,使得原先1个Region的压力得以分流到2个Region上。

可以看出HBase只有增添数据,所有的更新和删除操作都是在后续的Compact历程中举行的,使得用户的写操作只要进入内存就可以立刻返回,实现了HBase I/O的高机能。

2.2.2 读操作流程

  • (1) Client访问Zookeeper,查找-ROOT-表,获取.META.表信息。
  • (2) 从.META.表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer。
  • (3) 通过RegionServer获取需要查找的数据。
  • (4) Regionserver的内存分为MemStore和BlockCache两部分,MemStore主要用于写数据,BlockCache主要用于读数据。读请求先到MemStore中查数据,查不到就到BlockCache中查,再查不到就会到StoreFile上读,并把读的结果放入BlockCache。

寻址过程:client-->Zookeeper-->-ROOT-表-->.META.表-->RegionServer-->Region-->client

 

3. HBase数据模型

2.1 基本术语

Table(表格)

一个HBase表格由多行组成。

Row(行)

HBase中的行里面包含一个key和一个或者多个包含值的列。行按照行的key字母顺序存储在表格中。因为这个原因,行的key的设计就显得非常重要。数据的存储目标是相近的数据存储到一起。一个常用的行的key的格式是网站域名。如果你的行的key是域名,你应该将域名进行反转(org.apache.www, org.apache.mail, org.apache.jira)再存储。这样的话,所有Apache域名将会存储在一起,好过基于子域名的首字母分散在各处。

Column(列)

HBase中的列包含用:分隔开的列族和列的限定符。

Column Family(列族)

因为性能的原因,列族物理上包含一组列和它们的值。每一个列族拥有一系列的存储属性,例如值是否缓存在内存中,数据是否要压缩或者他的行key是否要加密等等。表格中的每一行拥有相同的列族,尽管一个给定的行可能没有存储任何数据在一个给定的列族中。

Column Qualifier(列的限定符)

列的限定符是列族中数据的索引。例如给定了一个列族content,那么限定符可能是content:html,也可以是content:pdf。列族在创建表格时是确定的了,但是列的限定符是动态地并且行与行之间的差别也可能是非常大的。

Cell(单元)

单元是由行、列族、列限定符、值和代表值版本的时间戳组成的。

Timestamp(时间戳)

时间戳是写在值旁边的一个用于区分值的版本的数据。默认情况下,时间戳表示的是当数据写入时RegionSever的时间点,但你也可以在写入数据时指定一个不同的时间戳。

 

2.2 逻辑视图

一个名为webable的表格,表格中有两行(com.cnn.www 和 com.example.www)和三个列族(contents, anchor, 和 people)。

在这个例子当中,第一行(com.cnn.www)中anchor包含两列(anchor:cnnsi.com, anchor:my.look.ca)和content包含一列(contents:html)。

这个例子中com.cnn.www拥有5个版本而com.example.www有一个版本。

contents:html列中包含给定网页的整个HTML。anchor限定符包含能够表示行的站点以及链接中文本。People列族表示跟站点有关的人。

Table webtable

Row Key

Time Stamp

ColumnFamily contents

ColumnFamily anchor

ColumnFamily people

 

列名

按照所定义好的,一个列名的格式为列族名前缀加限定符。例如,列contents:html由列族contents和html限定符。冒号(:)用于将列族和列限定符分开。

"com.cnn.www"

t9

 

anchor:cnnsi.com = "CNN"

 

"com.cnn.www"

t8

 

anchor:my.look.ca = "CNN.com"

 

"com.cnn.www"

t6

contents:html = "<html>…​"

   

"com.cnn.www"

t5

contents:html = "<html>…​"

   

"com.cnn.www"

t3

contents:html = "<html>…​"

   

com.example.www

t5

contents:html: "<html>..."

 

people:author: "John Doe"

在HBase中,表格中的单元如果是空将不占用空间或者事实上不存在。这就使得HBase看起来“稀疏”。表格视图不是唯一方式来查看HBase中数据,甚至不是最精确的。下面的方式以多维度映射的方式来表达相同的信息。下面只是一个用于说明目的的模型可能不是百分百的精确。

{
 
  "com.cnn.www": {
 
    contents: {
 
      t6: contents:html: "&lt;html&gt;..."
 
      t5: contents:html: "&lt;html&gt;..."
 
      t3: contents:html: "&lt;html&gt;..."
 
    }
 
    anchor: {
 
      t9: anchor:cnnsi.com = "CNN"
 
      t8: anchor:my.look.ca = "CNN.com"
 
    }
 
    people: {}
 
  }
 
  "com.example.www": {
 
    contents: {
 
      t5: contents:html: "&lt;html&gt;..."
 
    }
 
    anchor: {}
 
    people: {
 
      t5: people:author: "John Doe"
 
    }
 
  }
 
}

 

posted on 2018-07-08 14:22  波神  阅读(366)  评论(0编辑  收藏  举报