一、HBase 是什么?
HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统” 。就像 Bigtable 利用了 Google 文件系统(File System)所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。HBase 是 Apache 的 Hadoop 项目的子项目。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是 HBase 基于列的而不是基于行的模式。
二、HBase 的特点?
- 大:一个表可以有上亿行,上百万列。
- 面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
- 稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
- 无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列。
- 数据多版本:每个单元中的数据可以有多个版本,默认情况下,版本号自动分配,版本号就是单元格插入时的时间戳。
- 数据类型单一:HBase 中的数据都是字符串,没有类型。
- 支持过期:HBase 支持 TTL 过期特性。用户设置过期时间,超过 TTL 的数据会被系统自动清理。
三、Hbase 数据模型?
HBase 以表的形式存储数据。表由行和列组成。列划分为若干个列簇(column family),如下图所示。
![](https://img2020.cnblogs.com/blog/1153954/202104/1153954-20210401104149680-1480068388.png)
- 表(Table): HBase 会将数据组织进一张张的表里面,但是需要注意的是表名必须是能用在文件路径里的合法名字,因为 HBase 的表是映射成 hdfs 上面的文件。
- 行(Row): 在表里面,每一行代表着一个数据对象,每一行都是以一个行键(Row Key)来进行唯一标识的,行键并没有什么特定的数据类型, 以二进制的字节来存储。
- 列簇(Column Family): 在定义 HBase 表的时候需要提前设置好列簇, 表中所有的列都需要组织在列簇里面,列簇一旦确定后,就不能轻易修改,因为它会影响到 HBase 真实的物理存储结构,但是列簇中的列标识(Column Qualifier)以及其对应的值可以动态增删。表中的每一行都有相同的列簇,但是不需要每一行的列簇里都有一致的列标识(Column Qualifier)和值, 所以说是一种稀疏的表结构。
- 列标识(Column Qualifier): 列簇中的数据通过列标识来进行映射,其实这里可以不用拘泥于“列”这个概念,也可以理解为一个键值对,Column Qualifier 就是 Key。 列标识也没有特定的数据类型,以二进制字节来存储。
- 单元(Cell): 每一个行键,列簇和列标识共同组成一个单元,存储在单元里的数据称为单元数据,单元和单元数据也没有特定的数据类型,以二进制字节来存储。
- 时间戳(Timestamp): 默认下每一个单元中的数据插入时都会用时间戳来进行版本标识。读取单元数据时,如果时间戳没有被指定,则默认返回最新的数据。写入新的单元数据时,如果没有设置时间戳,默认使用当前时间。每一个列簇的单元数据的版本数量都 HBase 单独维护,默认情况下 HBase 保留 3 个版本数据。
RowKey
RowKey 可以使用任意字符串(最大长度为 64KB,实际应用中长度一般为 10 ~ 100bytes),在 HBase 内部,Row Key 保存为字节数组。
在 HBase 使用过程中,设计 RowKey 是一个很重要的环节。我们在进行 RowKey 设计的时候可参照如下步骤:
- 结合业务场景特点,选择合适的字段来做为 RowKey, 且按照查询频次来放置字段顺序。
- 通过设计的 RowKey 能尽可能的将数据打散到整个集群中,均衡负载,避免热点问题。
- 设计的 RowKey 应尽量简短。
与 NoSQL 一样,RowKey 是用来检索记录的主键。访问 HBase table 中的行,只有三种方式:
- 通过单个 RowKey 访问。
- 通过 scan 方式,设置 startRow 和 stopRow 参数进行范围匹配。
- 全表扫描,即直接扫描整张表中的所有行记录。
物理存储模型
物理存储上 HBase 将 Table 在行的方向上分割为多个 HRegion, 每个 HRegion 分散在不同的 HRegionServer 中。
![](https://img2020.cnblogs.com/blog/1153954/202104/1153954-20210401141952368-1752491473.png)
每个 HRegion 由多个 Store 构成, 每个 Store 由一个 memStore 和0或多个 StoreFile 组成, 每个 Store 保存一个 Columns Family。
![](https://img2020.cnblogs.com/blog/1153954/202104/1153954-20210401142017042-689191787.png)
四、Hbase 体系结构?
HBase 中的组件包括 Client、Zookeeper、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog 等。
![](https://img2020.cnblogs.com/blog/1153954/202104/1153954-20210401142356865-1917162264.png)
HBase 中的每张表都通过行键(RowKey)按照一定的范围被分割成多个子表(HRegion),一个 HRegion 超过一定阈值就要被分割成两个,这个过程由 HRegionServer
管理, 而 HRegion 的分配由 HMaster
管理。
HMaster
- 为 HRegion Server 分配 HRegion。
- 负责 HRegion Server 的负载均衡。
- 发现失效的 HRegion Server 并重新分配其上 HRegion。
- HDFS 上的垃圾文件回收。
- 处理 schema 更新请求。
HMaster 仅仅维护 HRegion 的元数据信息,而 table 的元数据信息保存在 zookeeper 上,因此,HMaster 的负载很低。
HRegion Server
- 维护 HMaster 分配给他的 HRegion,并处理对这些 HRegion 的 IO 请求(client 访问 HBase 上的数据并不需要 HMaster 参与)。
- 负责切分正在运行过程中变得过大的 HRegion。
HRegion
table 在行的方向上分割为多个 HRegion ,HRegion 是 HBase 中分布式存储和负载均衡的最小单元,即不同的 HRegion 可以分布在不同的 HRegion Server 上,但同一个 HRegion 是不会拆分到多个 HRegion Server 上。
HRegion 按大小分割,每个表一般只有一个 HRegion ,随着数据不断的插入表,HRegion 不断增大,当 HRegion 的某个列簇达到一定的阈值时就会分成两个新的 HRegion 。
Zookeeper
- 保证任何时候,集群中只有一个 HMaster,避免 HMaster 的单点故障。
- 存储所有 HRegion 的寻址入口。
- 实时监控 HRegion Server 的上线和下线信息,并实时通知 HMaster。
- 存储 HBase 的 schema 和 table 元数据。
HBase 依赖 Zookeeper,默认情况下 HBase 管理 Zookeeper 实例(启动或关闭 Zookeeper),HMaster 与 HRegionServers 启动时会向 Zookeeper 注册,使 HMaster 可以随时感知到各个 HRegionServer 的健康状态。
Client
首先当一个请求发生时,HBase Client 使用 RPC 机制与 HMaster 和 HRegion Server 进行通信。对于管理类操作,Client 与 HMaster 进行 RPC 通信;对于数据读写操作,Client 与 HRegion Server 进行 RPC 通信。
HBase Client 使用 RPC 机制与 HMaster 和 HRegion Server 进行通信,但如何寻址呢?由于 Zookeeper 中存储了 Meta 表的地址和 HMaster 的地址,所以 HBase Client 需要先到 Zookeeper 上进行寻址。
HBase Client 访问 Zookeeper,可以根据 Meta 表获取到 HRegion Server 地址。