image frame

无论走到哪里,
都应该记住,
过去都是假的,
回忆是一条没有尽头的路。
一切以往的春天都不复存在,
就连那最坚韧而又狂乱的爱情,
归根结底也不过是转瞬即逝的现实,
唯有孤独永恒。

——加西亚·马尔克斯

hbase 基础概念

导读

  1. HBase 是什么?有什么特性?
  2. HBase 有什么优势?
  3. HBase 使用哪些应用场景?
  4. HBase 有哪些组件,分别具有什么功能?
  5. HBase Region 如何进行分区及定位?
  6. HBase 数据读写流程?
  7. HBase WAL 机制是什么?
  8. HBase 是如何管理 Region 的?

NoSQL-HBase

HBase 是一个开源的、分布式的、版本化的非关系型数据库,它利用 Hadoop 分布式文件系统(Hadoop Distributed File System,HDFS)提供分布式数据存储。可以进行随机访问的存取和检索数据的存储平台,存储结构化和半结构化的数据.

HBase 特性:

  • 单条记录强一致性读写。
  • 自动分片。
  • RegionServer 自动故障转移。
  • Hadoop/HDFS 整合。
  • 支持 MapReduce。
  • 支持 Java API。
  • 支持 Thrift/REST API。
  • Block Cache 和 Bloom Filters 性能查询优化。
  • 基于网页的操作管理。

更多信息:
https://hbase.apache.org/book.html#arch.overview.nosql

HBase 优势

容量巨大

HBase 单表支持百亿行、百万列数据,可横向和纵向两个维度插入数据,弹性好。在限定某个列的情况下,对单个表存储百亿甚至更多的数据没有性能问题。

HBase 采用 LSM 树作为内部数据存储结构,这种结构会周期性地将较小文件合并成大文件,以减少对磁盘的访问。

LSM的原理:将对数据的修改增量保存在内存中,达到指定大小限制之后批量把数据flush到磁盘中,磁盘中树定期可以做merge操作,合并成一棵大树,以优化读性能。不过读取的时候稍微麻烦一些,读取时看这些数据在内存中,如果未能命中内存,则需要访问较多的磁盘文件。

更多关于LSM-tree:
https://www.cs.umb.edu/~poneil/lsmtree.pdf
https://www.researchgate.net/publication/226763355_The_log-structured_merge-tree_LSM-tree

列存储

HBase 是面向列的存储和权限控制的,它里面的每个列是单独存储的,且支持基于列的独立检索。

行存储里的一张表的数据都放在一起,但在列存储里是按照列分开保存的。
数据的插入和更新操作时,行存储会相对容易。
查询操作时,行存储需要读取所有的数据,而列存储则只需要读取相关列,可以大幅降低系统 I/O 吞吐量。

稀疏性

通常在传统的关系性数据库中,每一列的数据类型是事先定义好的,会占用固定的内存空间,在此情况下,属性值为空(NULL)的列也需要占用存储空间。

而在 HBase 中的数据都是以字符串形式存储的,为空的列并不占用存储空间,因此 HBase 的列存储解决了数据稀疏性的问题,在很大程度上节省了存储开销。所以 HBase 通常可以设计成稀疏矩阵,同时这种方式比较接近实际的应用场景。

扩展性强

HBase 工作在 HDFS 之上,理所当然地支持分布式表,也继承了 HDFS 的可扩展性。
HBase 表根据 Region 大小进行分区,分别存在集群中不同的节点上,当添加新的节点时,集群就重新调整,在新的节点启动 HBase 服务器,动态地实现扩展。

更多关于HDFS:
http://c.biancheng.net/view/6502.html

高可用性

HBase 运行在 HDFS 上,HDFS 的多副本存储可以让它在岀现故障时自动恢复,同时 HBase 内部也提供 WAL 和 Replication 机制。

WAL(Write-Ahead-Log)预写日志是在 HBase 服务器处理数据插入和删除的过程中用来记录操作内容的日志,保证了数据写入时不会因集群异常而导致写入数据的丢失;而 Replication 机制是基于日志操作来做数据同步的。

当集群中单个节点出现故障时,协调服务组件 ZooKeeper 通知集群的主节点,将故障节点的 HLog 中的日志信息分发到各从节点进行数据恢复

HBase 使用场景

HBase 解决不了所有的问题,但是针对某些特点的数据可以使用 HBase 高效地解决,如以下的应用场景。

  1. 数据模式是动态的或者可变的,且支持半结构化和非结构化的数据。
  2. 数据库中的很多列都包含了很多空字段,在 HBase 中的空字段不会像在关系型数据库中占用空间。
  3. 需要很高的吞吐量,瞬间写入量很大。
  4. 数据有很多版本需要维护,HBase 利用时间戳来区分不同版本的数据。
  5. 具有高可扩展性,能动态地扩展整个存储系统。

案例

  • Facebook 公司的 Social Inbox 系统,使用 HBase 作为消息服务的基础存储设施,每月可处理几千亿条的消息;
  • Yahoo 公司使用 HBase 存储检查近似重复的指纹信息的文档,它的集群当中分别运行着 Hadoop 和 HBase,表中存了上百万行数据;
  • Adobe 公司使用 Hadoop+HBase 的生产集群,将数据直接持续地存储在 HBase 中,并将 HBase 作为数据源进行 MapReduce 的作业处理;
  • Apache 公司使用 HBase 来维护 Wiki 的相关信息。

更多案例:
http://c.biancheng.net/view/6514.html

HBase的组件和功能

HBase 各个组件:

客户端

整个 HBase 系统的入口,使用 HBase RPC 机制于 HMaster 和 RegionServer 进行通信。

Zookeeper

ZooKeeper 是一个高性能、集中化、分布式应用程序协调服务。

协调任务如下:

  1. Master 选举
  2. 系统容错(协同HMaster管理RegionServer)
  3. Region 元数据管理

Region 元数据(Meta表)存储在 Zookeeper 中,客户端发起新的查询请求需要查询Meta表获取 Region 位置。

  1. Region 状态管理

HBase 集群中 Region 会经常发生变更,其原因可能是系统故障,配置修改,或者是 Region 的分裂和合并。只要 Region 发生变化,就需要让集群的所有节点知晓,否则就会出现某些事务性的异常。

  1. 提供 Meta 表存储位置

在 HBase 集群中,数据库表信息、列族信息及列族存储位置信息都属于元数据。这些元数据存储在 Meta 表中,而 Meta 表的位置入口由 ZooKeeper 来提供。

HMaster

HMaster 是 HBase 集群中的主服务器,负责监控集群中的所有 RegionServer,并且是所有元数据更改的接口。

在分布式集群中,HMaster 服务器通常运行在 HDFS 的 NameNode上,HMaster 通过 ZooKeeper 来避免单点故障,在集群中可以启动多个 HMaster,但 ZooKeeper 的选举机制能够保证同时只有一个 HMaster 处于 Active 状态,其他的 HMaster 处于热备份状态。

HMaster 主要负责表和 Region 的管理工作。

  1. 管理用户对表的增、删、改、查操作。
  2. 管理 RegionServer 的负载均衡,调整 Region 的分布。
  3. Region 的分配和移除。
  4. 处理 RegionServer 的故障转移。

RegionServer

RegionServer 主要负责响应用户的请求,向 HDFS 读写数据。一般在分布式集群中,RegionServer 运行在 DataNode 服务器上,实现数据的本地性。

RegionServer 是 HBase 中最核心的模块,其内部管理了一系列 Region 对象,每个 Region 由多个 HStore 组成,每个 HStore 对应表中一个列族的存储。

每个 RegionServer 包含多个 Region,它负责的功能如下:

  1. 处理分批给它的 Region。
  2. 处理客户端读写请求。
  3. 刷新缓存到 HDFS 中。
  4. 处理 Region 分片。
  5. 执行压缩。

HBase Region分区及定位

在 HBase 中,表的所有行都是按照 RowKey 的字典序排列的,表在行的方向上分割为多个分区(Region)。

每张表一开始只有一个 Region,但是随着数据的插入,HBase 会根据一定的规则将表进行水平拆分,形成两个 Region。当表中的行越来越多时,就会产生越来越多的 Region,而这些 Region 无法存储到一台机器上时,则可将其分布存储到多台机器上。

Master 主服务器把不同的 Region 分配到不同的 Region 服务器上,同一个行键的 Region 不会被拆分到多个 Region 服务器上。每个 Region 服务器负责管理一个 Region,通常在每个 Region 服务器上会放置 10 ~ 1000 个 Region,HBase中Region 的物理存储如下图所示。

客户端在插入、删除、查询数据时需要知道哪个 Region 服务器上存储所需的数据,这个查找 Region 的过程称为 Region 定位。
HBase 中的每个 Region 由三个要素组成,包括 Region 所属的表、第一行和最后一行。其中,第一个 Region 没有首行,最后一个 Region 没有末行。每个 Region 都有一个 RegionlD 来标识它的唯一性,Region 标识符就可以表示成“表名+开始行键+RegionID”。

Meta 表

Meta 表的每个条目包含两项内容,一项是 Region 标识符,另一项是 Region 服务器标识。这个条目就表示 Region 和 Region 服务器之间的对应关系,从而就可以使用户知道某个 Region 存储在哪个 Region 服务器中。

1
2
3
# scan 'hbase:meta'
ROW COLUMN+CELL
hbase:namespace,,1582440367299.c349a23aa3536a0c26e9 column=info:regioninfo, timestamp=1593651118107, value={ENCODED => c349a23aa3536a0c26e96e5f4201c03c, NAME => 'hbase:namespace,,1582440367299.c349a23aa36e5f4201c03c.536a0c26e96e5f4201c03c.', STARTKEY => '', ENDKEY => ''}

Meta 表里有一个列族 info。info 包含了三个列,分别为 RegioninfoServer 和 Serverstartcode。Regionlnfo中记录了 Region 的详细信息,包括行键范围 StartKey 和 EndKey、列族列表和属性。

Region 定位

Hbase 二层架构的 Region 定位流程:

  1. 找 Meta 表位置信息

    通过 ZooKeeper 中的 /hbase/meta-region-server 先找到 Meta 表所在的 Region 服务器信息,从中获取分区 Meta 表位置。

  2. 根据 Meta 表位置信息定位 Region,找出 Region 所在的 Region 服务器。
  3. 通过 Mate 表得到所需的表和行键所在的 Region 信息,然后从 Region 服务器上找到所需的数据。

详细信息:
http://c.biancheng.net/view/6528.html

HBase 数据的读写流程

HBase 的核心模块是 Region 服务器。Region 服务器由多个 Region 块构成,Region 块中存储一系列连续的数据集。Region 服务器主要构成部分是 HLog 和 Region 块。HLog 记录该 Region 的操作日志。

Region 对象由多个 Store 组成,每个 Store 对应当前分区中的一个列族,每个 Store 管理一块内存。当 MemStore 中的数据达到一定条件时会写入 StoreFile 文件中,因此每个 Store 包含若干个 StoreFile 文件。StoreFile 文件对应 HDFS 中的 HFile 文件。

HBase 群集数据的构成如图所示。

MemStore

当 Region 服务器收到写请求的时候,Region 服务器会将请求转至相应的 Region。数据先被写入 MemStore,当到达一定的阈值时,MemStore 中的数据会被刷新到 HFile 中进行持久化存储。

HBase 将最近接收到的数据缓存在 MemStore 中,在持久化到 HDFS 之前完成排序,再顺序写入 HDFS,为后续数据的检索进行优化。因为 MemStore 缓存的是最近增加的数据,所以也提高了对近期数据的操作速度。

Store

Store 是 Region 服务器的核心,存储的是同一个列族下的数据,每个 Store 包含一块 MemStore 和 StoreFile( 0 个或多个)。StoreFile 是 HBase 中最小的数据存储单元。

数据写入 MemStore 缓存,当 MemStore 缓存满时,内存中的数据会持久化到磁盘中一个 StoreFile 文件中,随着 StoreFile 文件数量的不断增加,数量达到一个阈值后,就会促使文件合并成一个大的 StoreFile 文件。

由于 StoreFile 文件的不断合并,造成 StoreFile 文件的大小超过一定的阈值,因此,会促使文件进行分裂操作。同时,当前的一个父 Region 会被分成两个子 Region, 父 Region 会下线,新分裂出的两个子 Region 会被 Master 分配到相应的 Regio n服务器上。

Store 的合并和分裂过程如下图所示。

HFile

将 MemStore 内存中的数据写入 StoreFile 文件中,StoreFile 底层是以 HFile 格式保存的。

HFile 的存储格式如下图所示。

HFile 文件是不定长的,长度固定的只有其中的两块:Trailer 和 File Info。Trailer 中有指针指向其他数据块的起始点,File Info 记录了文件的一些 Meta 信息。每个 Data 块的大小可以在创建一个 Table 的时候通过参数指定(默认块大小为 64KB)。每个 Data 块除了开头的 Magic 以外就是由一个键值对拼接而成的,Magic 内容是一些随机数字,用于防止数据损坏。

HFile 里面的每个键值对就是一个简单的 Byte 数组。但是这个 Byte 数组里面包含了很多项, 并且有固定的结构,其具体结构如图所示。

键值对结构以两个固定长度的数值开始,分别表示 Key 的长度和 Value 的长度。紧接着是 Key,Key 以 RowLength 开始,是固定长度的数值,表示 RowKey 的长度;接着是 Row,然后是固定长度的数值 ColumnFamilyLength,表示 Family 的长度;之后是 Family 列族,接着是 Qualifier 列标识符,Key 最后以两个固定长度的数值 Time Stamp 和 Key Type(Put/Delete) 结束。Value部分没有这么复杂的结构,就是纯粹的二进制数据。

HBase 数据写入流程

1) 客户端访问 ZooKeeper,从 Meta 表得到写入数据对应的 Region 信息和相应 的Region 服务器。

2) 客户端访问相应的 Region 服务器,把数据分别写入 HLog 和 MemStore。MemStore 数据容量有限,当达到一个阈值后,则把数据写入磁盘文件 StoreFile 中,在 HLog 文件中写入一个标记,表示 MemStore 缓存中的数据已被写入 StoreFile 中。如果 MemStore 中的数据丢失,则可以从 HLog 上恢复。

3) 当多个 StoreFile 文件达到阈值后,会触发 Store.compact() 将多个 StoreFile 文件合并为一个 大文件。

HBase 数据读取流程

1) 客户端先访问 ZooKeeper,从 Meta 表读取 Region 信息对应的服务器。

2) 客户端向对应 Region 服务器发送读取数据的请求,Region 接收请求后,先从 MemStore 查找数据;如果没有,再到 StoreFile 上读取,然后将数据返回给客户端。

HBase WAL机制

Region服务器发生故障时, MemStore 缓存中还没有被写入文件的数据会全部丢失。因此,HBase 采用 HLog 来保证系统发生故障时能够恢复到正常的状态。

每个 Region 服务器都有一个 HLog 文件,同一个 Region 服务器的 Region 对象共用一个 HLog,HLog 是一种预写日志(Write Ahead Log)文件。

预写日志文件(WAL)保存在 HDFS 上,目录:/hbase/WALs/ , 每个子目录对应一个 Region 。

用户更新数据必须先被记入日志后才能写入 MemStore 缓存,当缓存内容对应的日志已经被写入磁盘后,即日志写成功后,缓存的内容才会被写入磁盘。

ZooKeeper 会实时监测每个 Region 服务器的状态,当某个 Region 服务器发生故障时,ZooKeeper 会通知 Master,Master 首先会处理该故障 Region 服务器上遗留的 HLog 文件。

系统会根据每条日志记录所属的 Region 对象对 HLog 数据进行拆分,并分别存放到相应 Region 对象的目录下。再将失效的 Region 重新分配到可用的 Region 服务器中,并在可用的 Region 服务器中重新进行日志记录中的各种操作, 把日志记录中的数据写入 MemStore 然后刷新到磁盘的 StoreFile 文件中,完成数据恢复。

Region 对象共用一个 HLog 的方式中,多个 Region 对象在进行更新操作需要修改日志时,只需要不断地把日志记录追加到单个日志文件中,而不需要同时打开、写入多个日志文件中,因此可以减少磁盘寻址次数,提高对表的写操作性能。

https://hbase.apache.org/book.html#wal
http://c.biancheng.net/view/6533.html

HBase Region管理

Region 是 HBase 集群的负载均衡和数据分发的基本单元。当 HBase中 表的容量非常庞大时,用户就需要将表中的内容分布到多台机器上。那么,需要根据行键的值对表中的行进行划分,每个行区间构成一个 Region,一个 Region 包含了位于某个阈值区间的所有数据。

HFile 合并

每个 RegionServer 包含多个 Region,而每个 Region 又对应多个 Store,每一个 Store 对应表中一个列族的存储,且每个 Store 由一个 MemStore 和多个 StoreFile 文件组成。

StoreFile 在底层文件系统中由 HFile 实现,也可以把 Store 看作由一个 MemStore 和多个 HFile 文件组成。MemStore 充当内存写缓存,默认大小 64MB,当 MemStore 超过阈值时,MemStore 中的数据会刷新到一个新的 HFile 文件中来持久化存储。

久而久之,每个 Store 中的 HFile 文件会越来越多,I/O 操作的速度也随之变慢,读写也会延时,导致慢操作。因此,需要对 HFile 文件进行合并,让文件更紧凑,让系统更有效率。

HFile 的合并分为两种类型,分别是 Minor 合并和 Major 合并。

Minor 合并

Minor 合并是把多个小 HFile 合并生成一个大的 HFile。
执行合并时,HBase 读出已有的多个 HFile 的内容,把记录写入一个新文件中。然后把新文件设置为激活状态,并标记旧文件为删除。

Major 合并

Major 合并针对的是给定 Region 的一个列族的所有 HFile,将 Store 中的所有 HFile 合并成一个大文件,有时也会对整个表的同一列族的 HFile 进行合并,这是一个耗时和耗费资源的操作,会影响集群性能。

Region 拆分

Region 拆分是 HBase 能够拥有良好扩展性的最重要因素。一旦 Region 的负载过大或者超过阈值时,它就会被分裂成两个新的 Region.

这个过程是由 RegionServer 完成的,其拆分流程如下。

  1. 将需要拆分的 Region下线,阻止所有对该 Region 的客户端请求,Master 会检测到 Region 的状态为 SPLITTING。
  2. 将一个 Region 拆分成两个子 Region,先在父 Region下建立两个引用文件,分别指向 Region 的首行和末行,这时两个引用文件并不会从父 Region 中复制数据。
  3. 之后在 HDFS 上建立两个子 Region 的目录,分别复制上一步建立的引用文件,每个子 Region 分别占父 Region 的一半数据。复制登录完成后删除两个引用文件。
  4. 完成子 Region 创建后,向 Meta 表发送新产生的 Region 的元数据信息。
  5. 将 Region 的拆分信息更新到 HMaster,并且每个 Region 进入可用状态。

拆分策略:

  1. ConstantSizeRegionSplitPolicy
  2. IncreasingToUpperBoundRegionSplitPolicy
  3. SteppingSplitPolicy
  4. DisabledRegionSplitPolicy

Region 合并

从 Region 的拆分过程中可以看到,随着表的增大,Region 的数量也越来越大。如果有很多 Region,它们中 MemStore 也过多,会频繁出现数据从内存被刷新到 HFile 的操作,从而会对用户请求产生较大的影响,可能阻塞该 Region 服务器上的更新操作。过多的 Region 会增加 ZooKeeper 的负担。

因此,当 Region 服务器中的 Region 数量到达阈值时,Region 服务器就会发起 Region 合并,其合并过程如下。

  1. 客户端发起 Region 合并处理,并发送 Region 合并请求给 Master。
  2. Master 在 Region 服务器上把 Region 移到一起,并发起一个 Region 合并操作的请求。
  3. Region 服务器将准备合并的 Region下线,然后进行合并。
  4. 从 Meta 表删除被合并的 Region 元数据,新的合并了的 Region 的元数据被更新写入 Meta 表中。
  5. 合并的 Region 被设置为上线状态并接受访问,同时更新 Region 信息到 Master。

Region 负载均衡

Region 的负载均衡由 Master 来完成,Master 有一个内置的负载均衡器,在默认情况下,均衡器每 5 分钟运行一次,用户可以配置。负载均衡操作分为两步进行:首先生成负载均衡计划表, 然后按照计划表执行 Region 的分配。

执行负载均衡前要明确,在以下几种情况时,Master 是不会执行负载均衡的。

  • 均衡负载开关关闭。
  • Master 没有初始化。
  • 当前有 Region 处于拆分状态。
  • 当前集群中有 Region 服务器出现故障。

Master 内部使用一套集群负载评分的算法,来评估 HBase 某一个表的 Region 是否需要进行重新分配。这套算法分别从 Region 服务器中 Region 的数目、表的 Region 数、MenStore 大小、 StoreFile 大小、数据本地性等几个维度来对集群进行评分,评分越低代表集群的负载越合理。

负载均衡策略:

  1. RandomRegionPicker
  2. LoadPicker
  3. LocalityBasedPicker

http://c.biancheng.net/view/6539.html

总结

  1. HBase 是分布式的非关系型数据库,支持多版本数据存储。容量大,支持百亿行,百万列的数据存储。
  2. HBase 不支持事务,但是支持单条数据强一致性的读写。
  3. HBase 中,表的所有行都是按照 RowKey 的字典序排列的,表在行的方向上分割为多个分区(Region)。
  4. HBase 自动分片技术是通过 Region 的自动拆分、合并实现的,数据的读写都需要定位对应的 Region。
  5. HBase 通过预写日志 WAL (Write Ahead Log) 保证 Region 故障恢复,Region 共用一个 HLog 文件。
  6. HBase 底层是基于 LSM-tree 实现,所以 HBase 的写过程是先写 HLog 和 MemStore,再刷新到磁盘。读过程是先查询 Memtore 是否存在,不存在再检索磁盘。
  7. LSM-tree 使得 HBase 实现了批量数据写入磁盘,大大提高数据写入性能。但是数据存储被拆分成了两个部分,一部分保存在磁盘、另一部分缓存在内存,不得不牺牲一部分读性能。
  8. 为了提升查询效率,HBase 使用了 BloomFilter 缩减查询范围,同时对 storefile 进行合并,减少磁盘寻址次数。

参考文档

https://hbase.apache.org/book.html#regionserver.offheap.overview
http://c.biancheng.net/view/6499.html

  • © 2015-2020 Andrew
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信