Hbase系统架构及数据结构

This commit is contained in:
罗祥 2019-05-31 10:32:59 +08:00
parent 9efe76b9cc
commit 16fa2da716

View File

@ -27,19 +27,17 @@
### 2.1 Row Key (行键)
Row Key是用来检索记录的主键。访问HBase Table中的行只有三种方式:
`Row Key`是用来检索记录的主键。想要访问HBase Table中的数据只有以下三种方式:
+ 通过单个Row Key访问
+ 通过指定`Row Key`进行访问;
+ 通过Row Key的range
+ 通过Row Key的range进行访问,即访问指定`Row Key`范围内的行的数据;
+ 全表扫描
+ 进行全表扫描
Row Key (行键)可以是任意字符串(最大长度是 64KB实际应用中长度一般为 10-100bytes)在HBase内部Row Key保存为字节数组。存储时数据按照Row Key的字典序(byte order)排序存储。
`Row Key`可以是任意字符串,存储时,数据按照`Row Key`的字典序进行排序。需要注意以下两点:
需要注意以下两点:
+ 字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。要保持整型的自然序行键必须用0作左填充。
+ 因为字典序对Int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。如果你使用整型的字符串作为行键那么为了保持整型的自然序行键必须用0作左填充。
+ 行的一次读写是原子操作 (不论一次读写多少列)。
@ -47,31 +45,31 @@ Row Key (行键)可以是任意字符串(最大长度是 64KB实际应用中
### 2.2 Column Family列族
HBase表中的每个列Column都归属与某个列族。列族是表的schema的一部分(列不是),必须在使用表之前定义。列名都以列族作为前缀。例如`courses:history``courses:math`都属于`courses `这个列族。
HBase表中的每个列都归属于某个列族。列族是表的Schema的一部分所以列族需要在创建表时进行定义。列族的所有列都以列族名作为前缀例如`courses:history``courses:math`都属于`courses `这个列族。
### 2.3 Column Qualifier (列限定符)
列限定符被添加到列族中,以提供给定数据的索引。给定列族`content`,列限定符可能是`content:html`,另一个可能是`content:pdf`。虽然列族在创建表时是固定的,但列限定符是可变的,并且行与行之间可能有很大差异
列限定符,你可以理解为是具体的列名,例如`courses:history``courses:math`都属于`courses `这个列族,它们的列限定符分别是`history``math`。需要注意的是列限定符不是表Schema的一部分你可以在插入数据的过程中动态创建列
### 2.4 Column(列)
HBase 中的列由列族和列限定符组成,它们由`:`(冒号)字符分隔。
HBase中的列由列族和列限定符组成它们由`:`(冒号)字符分隔,即一个完整的列名应该表述为`列族名 :列限定符`
### 2.5 Cell
Cell是行列族和列限定符的组合并包含值和时间戳。
`Cell`是行,列族和列限定符的组合,并包含值和时间戳。你可以等价理解为关系型数据库中由指定行和指定列确定的一个单元格但不同的是HBase中的一个单元格是由多个版本的数据组成的每个版本的数据用时间戳进行区分。
### 2.6 Timestamp(时间戳)
HBase 中通过`row``columns`确定的为一个存储单元称为Cell。每个Cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由HBase(在数据写入时自动 )赋值此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突就必须自己生成具有唯一性的时间戳。每个Cell中不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
HBase 中通过`row``columns`确定的为一个存储单元称为Cell。每个`Cell`都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由HBase在数据写入时自动赋值,也可以由客户显式指定。每个`Cell`中,不同版本的数据按照时间倒序排列,即最新的数据排在最前面。
@ -79,80 +77,82 @@ HBase 中通过`row`和`columns`确定的为一个存储单元称为Cell。每
### 2.1 Regions
HBase Table中的所有行都按照Row Key的字典序排列。HBase Tables 通过行键的范围row key range被水平切分成多个Region, 一个Region包含了在start key 和 end key之间的所有行。
HBase Table中的所有行都按照`Row Key`的字典序排列。HBase Tables 通过行键的范围(row key range)被水平切分成多个`Region`, 一个`Region`包含了在start key 和 end key之间的所有行。
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/HBaseArchitecture-Blog-Fig2.png"/> </div>
每个表一开始只有一个Region随着数据不断插入表Region不断增大当增大到一个阀值的时候Region就会等分会两个新的Region。当Table中的行不断增多就会有越来越多的Region。
每个表一开始只有一个`Region`,随着数据不断增加,`Region`会不断增大,当增大到一个阀值的时候,`Region`就会等分为两个新的`Region`。当Table中的行不断增多就会有越来越多的`Region`
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-region-splite.png"/> </div>
Region是HBase中**分布式存储和负载均衡的最小单元**。最小单元就表示不同的Region可以分布在不同的Region Server上。但一个Region是不会拆分到多个server上的。
`Region`是HBase中**分布式存储和负载均衡的最小单元**。这意味着不同的`Region`可以分布在不同的`Region Server`上。但一个`Region`是不会拆分到多个Server上的。
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-region-dis.png"/> </div>
### 2.2 Region Server
Region Server在HDFS DataNode上运行。
`Region Server`运行在HDFS的DataNode上。它具有以下组件
- **WAL(Write Ahead Log预写日志)**:用于存储尚未进持久化存储的数据记录,以便在发生故障时进行恢复;
- **BlockCache**:读缓存。它将频繁读取的数据存储在内存中。如果存储不足,它将按照`最近最少使用原则`清除多余的数据;
- **MemStore**写缓存。它存储尚未写入磁盘的新数据并会在数据写入磁盘之前对其进行排序。每个Region上的每个列族都有一个MemStore
- **HFile** 将行数据按照Key\Values的形式存储在文件系统上。
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-Region-Server.png"/> </div>
Region Server存取一个子表时会创建一个Region对象然后对表的每个列族创建一个`Store`实例,每个`Store`会有 0 个或多个`StoreFile`与之对应,每个`StoreFile`则对应一个`HFile`HFile 就是实际存储在HDFS上的文件。
<div align="center"> <img src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-hadoop.png"/> </div>
Region Server存取一个子表时会创建一个 Region 对象,然后对表的每个列族 (Column Family) 创建一个 Store 实例,每个 Store 都会有 0 个或多个 StoreFile 与之对应,每个 StoreFile 都会对应一个 HFileHFile 就是实际的存储文件。因此,一个 Region 有多少个列族就有多少个 Store。
Region Server还具有以下组件
+ WALWrite Ahead Log预写日志是分布式文件系统上的文件。 WAL用于存储尚未进持久化存储的新数据以便在发生故障时进行恢复。
+ BlockCache是读缓存。它将频繁读取的数据存储在内存中。如果存储不足它将按照`最近最少使用原则`清除多余的数据。
+ MemStore是写缓存。它存储尚未写入磁盘的新数据并会在数据写入磁盘之前对其进行排序。每个Region上的每个列族都有一个MemStore。
+ HFile将行数据按照KeyValues的形式存储在文件系统上。
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-Region-Server.png"/> </div>
## 三、Hbase系统架构
### 3.1 系统架构
HBase系统遵循Master/Salve架构由三种不同类型的组件组成
HBase系统遵循Master/Salve架构由三种不同类型的组件组成
**Zookeeper**
1. 保证任何时候集群中只有一个Master
1. 保证任何时候集群中只有一个Master
2. 存贮所有Region的寻址入口
2. 存贮所有Region的寻址入口
3. 实时监控Region Server的状态将Region server的上线和下线信息实时通知给Master
3. 实时监控Region Server的状态将Region server的上线和下线信息实时通知给Master
4. 存储HBase的schema,包括有哪些Table每个Table有哪些Column Family
4. 存储HBase的Schema包括有哪些Table每个Table有哪些Column Family等信息。
**Master**
1. 为Region server分配Region
1. 为Region Server分配Region
2. 负责Region server的负载均衡
2. 负责Region Server的负载均衡
3. 发现失效的Region server并重新分配其上的Region
3. 发现失效的Region Server并重新分配其上的Region
4. GFS上的垃圾文件回收
4. GFS上的垃圾文件回收
5. 处理schema更新请求
5. 处理Schema的更新请求。
**Region Server**
1. Region server维护Master分配给它的Region 处理发到Region上的IO请求
1. Region Server负责维护Master分配给它的Region 并处理发送到Region上的IO请求
2. Region server负责切分在运行过程中变得过大的Region
2. Region Server负责切分在运行过程中变得过大的Region
<div align="center"> <img width="600px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/HBaseArchitecture-Blog-Fig1.png"/> </div>
### 3.2 组件间的协作
HBase使用ZooKeeper作为分布式协调服务来维护集群中的服务器状态。 Zookeeper维护可用服务列表并提供服务故障通知
HBase使用ZooKeeper作为分布式协调服务来维护集群中的服务器状态。 Zookeeper负责维护可用服务列表,并提供服务故障通知等服务:
+ 每个Region Server都会在ZooKeeper上创建一个临时节点HMaster通过Zookeeper的Watcher机制监控这些节点以发现可用的Region Server和故障的Region Server
+ 每个Region Server都会在ZooKeeper上创建一个临时节点Master通过Zookeeper的Watcher机制对节点进行监控从而可以发现新加入的Region Server或故障退出的Region Server
+ Masters会竞争创建临时节点 Zookeeper确定第一个并使用它来确保只有一个主服务器处于活动状态。主Master向Zookeeper发送心跳备用HMaster监听主HMaster故障的通知在主HMaster发生故障的时候取而代之。
+ 所有Masters会竞争性地在Zookeeper上创建同一个临时节点由于Zookeeper只能有一个同名节点所以必然只有一个Master能够创建成功此时该Master就是主Master主Master会定期向Zookeeper发送心跳。备用Masters则通过Watcher机制对主HMaster所在节点进行监听
+ 如果Region Server或主HMaster未能发送心跳则会话过期并删除相应的临时节点。这会触发定义在该节点上的Watcher事件使得Region Server或备用Region Server得到通知
+ 如果主Master未能定时发送心跳则其持有的Zookeeper会话会过期相应的临时节点也会被删除这会触发定义在该节点上的Watcher事件使得备用的Master Servers得到通知。所有备用的Master Servers在接到通知后会再次去竞争性地创建临时节点完成首领选举
<div align="center"> <img src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/HBaseArchitecture-Blog-Fig5.png"/> </div>
@ -162,19 +162,19 @@ HBase系统遵循Master/Salve架构由三种不同类型的组件组成。
### 4.1 写入数据的流程
1. client向Region server提交写请求
1. Client向Region Server提交写请求
2. Region server找到目标Region
2. Region Server找到目标Region
3. Region检查数据是否与schema一致
3. Region检查数据是否与Schema一致
4. 如果客户端没有指定版本,则获取当前系统时间作为数据版本
4. 如果客户端没有指定版本,则获取当前系统时间作为数据版本
5. 将更新写入WAL log
5. 将更新写入WAL Log
6. 将更新写入Memstore
6. 将更新写入Memstore
7. 判断Memstore存储是否已满如果存储已满则需要flush为Store Hfile文件
7. 判断Memstore存储是否已满如果存储已满则需要flush为Store Hfile文件
> 更为详细写入流程可以参考:[HBase 数据写入流程解析](http://hbasefly.com/2016/03/23/hbase_writer/)
@ -182,15 +182,15 @@ HBase系统遵循Master/Salve架构由三种不同类型的组件组成。
### 4.2 读取数据的流程
以下是客户端首次读写Hbase 的流程:
以下是客户端首次读写HBase上数据的流程:
1. 客户端从Zookeeper获取 META 表所在的Region Server。
1. 客户端从Zookeeper获取`META`表所在的Region Server
2. 客户端访问 META 表所在的Region Server查询META 表获取它想访问的行键Row Key所在的Region Server。客户端将缓存这些信息以及META表的位置。
2. 客户端访问`META`表所在的Region Server`META`表中查询到访问行键所在的Region Server之后客户端将缓存这些信息以及`META`表的位置;
3. 客户端端将从相应的Region Server获取行数据。
3. 客户端从行键所在的Region Server上获取数据。
如果再次读取,客户端将使用缓存来获取META 的位置及之前的行键。这样时间久了客户端不需要查询META表除非Region移动所导致的缓存失效,这样的话,则将会重新查询更新缓存。
如果再次读取,客户端从缓存中获取行键所在的Region Server。这样客户端就不需要再次查询`META`除非Region移动导致缓存失效,这样的话,则将会重新查询更新缓存。
META 表是HBase中一张特殊的表它保存了HBase中所有数据表的Region位置信息ZooKeeper存储着META 表的位置。