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: "<html>..." t5: contents:html: "<html>..." t3: contents:html: "<html>..." } anchor: { t9: anchor:cnnsi.com = "CNN" t8: anchor:my.look.ca = "CNN.com" } people: {} } "com.example.www": { contents: { t5: contents:html: "<html>..." } anchor: {} people: { t5: people:author: "John Doe" } } }
hadoop学习笔记(六):HBase体系结构和数据模型的更多相关文章
- Hadoop学习笔记之HBase Shell语法练习
Hadoop学习笔记之HBase Shell语法练习 作者:hugengyong 下面我们看看HBase Shell的一些基本操作命令,我列出了几个常用的HBase Shell命令,如下: 名称 命令 ...
- Hadoop学习笔记—15.HBase框架学习(基础知识篇)
HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型,它存储的是 ...
- Hadoop学习笔记—15.HBase框架学习(基础实践篇)
一.HBase的安装配置 1.1 伪分布模式安装 伪分布模式安装即在一台计算机上部署HBase的各个角色,HMaster.HRegionServer以及ZooKeeper都在一台计算机上来模拟. 首先 ...
- hadoop学习笔记之-hbase完全分布模…
安装环境: OS: Oracle linux 5.6 JDK: jdk1.6.0_18 Hadoop: hadoop-0.20.2 Hbase: hbase-0.90.5 安装准备: 1. Jdk环境 ...
- hadoop学习笔记之-hbase完全分布模式安装-5
http://blog.csdn.net/lichangzai/article/details/8441975 http://blog.csdn.net/jpiverson/article/detai ...
- hadoop学习笔记-目录
以下是hadoop学习笔记的顺序: hadoop学习笔记(一):概念和组成 hadoop学习笔记(二):centos7三节点安装hadoop2.7.0 hadoop学习笔记(三):hdfs体系结构和读 ...
- Hadoop学习笔记(2)
Hadoop学习笔记(2) ——解读Hello World 上一章中,我们把hadoop下载.安装.运行起来,最后还执行了一个Hello world程序,看到了结果.现在我们就来解读一下这个Hello ...
- Hadoop学习笔记(2) ——解读Hello World
Hadoop学习笔记(2) ——解读Hello World 上一章中,我们把hadoop下载.安装.运行起来,最后还执行了一个Hello world程序,看到了结果.现在我们就来解读一下这个Hello ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- Hadoop学习笔记系列
Hadoop学习笔记系列 一.为何要学习Hadoop? 这是一个信息爆炸的时代.经过数十年的积累,很多企业都聚集了大量的数据.这些数据也是企业的核心财富之一,怎样从累积的数据里寻找价值,变废为宝炼 ...
随机推荐
- License 校验
1:了解keytool 的一些命令 http://www.micmiu.com/lang/java/keytool-start-guide/ 本人在github找的一个demo:https://gi ...
- Data Guard 介绍
- Shiro权限总结
参考学习地址 shiro 瞅完就会用(ssm+shiro) Spring Shiro配置实现用户认证和授权 anon:它对应的过滤器里面是空的,什么都没做,另外.do和.jsp后面的*表示参 ...
- 将*.sql数据库脚本导入到sqlserver中(sql文件导入sqlserver)
在SqlServer中这个是用生成sql脚本生成的 要是在导入数据库用数据导入/导出向导导不进去 其实要用查询分析器来打开sql文件 然后执行就可以了
- Haskell语言学习笔记(27)Endo, Dual, Foldable
Endo Monoid newtype Endo a = Endo { appEndo :: a -> a } instance Monoid (Endo a) where mempty = E ...
- k8s 问题
kubelet: Orphaned pod "4db449f0-4eaf-11e8-94ab-90b8d042b91a" found, but volume paths are s ...
- 关于Application.DoEvents()==转
记得第一次使用Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示,不至于系统出现假死的现象,当时也没有深入的去研究他的原理是怎样的,结果在很多地方都用上了App ...
- Ubuntu Server17.10配置静态IP
今天心血来潮,装个虚拟机Ubuntu打算学点东西,遇到了一些问题,同时借助百度的力量解决了,下面是配置的过程. 一. 安装virtualbox 不知道从哪个版本开始,安装虚拟盒子的时候没有了安装虚拟网 ...
- suse安装gcc,升级到4.8.5
前面这些是挂载iso,如果iso可以使用,就不需要下面几步. cd /etc/zypp/repos.d mkdir iso chmod -R 777 iso mount -o loop /media/ ...
- np.array()
将列表list或元组tuple转换为 ndarray 数组. numpy.array(object, dtype=None, copy=True, order=None, subok=False, n ...