深入HBase——引入

发布于:2025-02-13 ⋅ 阅读:(138) ⋅ 点赞:(0)

引入

前面我们通过深入HDFS深入MapReduce ,从设计和落地,去深入了解了大数据最底层的基石——存储与计算是如何实现的。

这个专栏则开始来看大数据的三驾马车中最后一个。

通过前面我们对于GFS和MapReduce论文实现的了解,我们知道GFS在数据写入时,只对顺序写入有比较弱的一致性保障,而对于数据读取,虽然GFS支持随机读取,但在当时的硬件条件下,实际上也是支撑不了真正的高并发读取的;此外,MapReduce虽然是一个批量处理数据的框架,吞吐量很大,但其延时和额外开销也不小。

在计算机数据存储领域,一直是关系数据库(RDBMS)的天下,以至于在传统企业的应用领域,许多应用系统设计都是面向数据库设计,也就是先设计数据库然后设计程序,从而导致关系模型绑架对象模型,并由此引申出旷日持久的业务对象贫血模型(业务逻辑由服务层处理,领域对象只包含数据。服务层通过调用领域对象的属性和方法来完成业务逻辑。)与充血模型(业务逻辑在领域对象中实现。领域对象不仅包含数据,还包含与数据相关的业务逻辑。服务层只负责接收用户的请求,并调用领域对象的方法来完成业务逻辑。)之争。

业界为了解决关系数据库的不足,提出了诸多方案,比较有名的是对象数据库,但是这些数据库的出现似乎只是进一步证明关系数据库的优越而已。直到人们遇到了关系数据库难以克服的缺陷——糟糕的海量数据处理能力及僵硬的设计约束,局面才有所改善。从Google的BigTable开始,一系列的可以进行海量数据存储与访问的数据库被设计出来,更进一步说,NoSQL这一概念被提了出来。

NoSQL主要指非关系的、分布式的、支持海量数据存储的数据库设计模式。不过随着技术的演进,NoSQL的解释也从最初的“No SQL”到现在的“Not Only SQL”,表示NoSQL只是关系数据库的补充,而不是替代方案。其中,HBase是这一类NoSQL系统的杰出代表。

HBase之所以能够具有海量数据处理能力,其根本在于和传统关系型数据库设计的不同思路。传统关系型数据库对存储在其上的数据有很多约束,学习关系数据库都要学习数据库设计范式,事实上,是在数据存储中包含了一部分业务逻辑。而NoSQL数据库则简单暴力地认为,数据库就是存储数据的,业务逻辑应该由应用程序去处理。

我们可以梳理出来,Bigtable要解决核心问题就是:如何支撑业务海量数据的随机读写(例如百万级别的随机读写IOPS)。

我们自然而然能想到的就是借鉴GFS的设计思路,除此之外还需要考虑到实时处理场景下如何提高容错。

Bigtable的答案,其实总结起来就三点:

  1. 将整个系统的存储层,搭建在GFS上。然后通过单Master调度多Tablets的方式,使得整个集群非常容易伸缩和维护。

  2. 通过MemTable+SSTable这样一个底层文件格式,解决高速随机读写数据的问题。

  3. 通过Chubby这个高可用的分布式锁服务解决一致性的挑战。

而本专栏的主角HBase,就是源自于Google的Bigtable论文。

HBase 同样利用 HDFS 作为底层存储,但是并不是简单地使用原本的数据,只是使用 HDFS 作为它的存储系统。也就是说,HBase 只是利用 Hadoop 的 HDFS 帮助其管理数据的持久化文件。HBase 提供超大规模数据集的实时随机读写,弥补了早期 Hadoop只能离线处理数据的不足。

一句话概括的话,HBase就是基于Hadoop构建的一个高可用、高性能、多版本的分布式NoSQL数据库,是Google BigTable的开源实现,通过在廉价服务器上搭建大规模结构化存储集群,提供海量数据高性能的随机读写能力。

下面我们先通过HBase的一些核心概念去初步了解一下它。

基本概念

  1. 表(Table):HBase中的表由行和列组成,一个表包含多行数据。表中的数据按照RowKey进行排序存储,支持范围查询。

  2. 行(row):,一行数据包含一个唯一标识rowkey、多个column以及对应的值。在HBase中,一张表中所有row都按照rowkey的字典序由小到大排序。

  3. 行键(Row Key):行是表中数据的基本单位,由RowKey标识。RowKey是字节序列,可以是任意长度,通常设计为能够反映数据的逻辑顺序。这是我们一行数据的唯一标识,比如说我们平时的数据都会有一个唯一 ID,就可以用来作为 Row Key。但是需要注意的是,HBase 在存储 Row Key 的时候是按照字典顺序存放的,所以如果你的 Row Key 不是以分布均匀的数字或字母开头的,很可能造成存储集中在某一台机器上,这会大大降低查询效率,所以这种时候需要设计存储的 Row Key,比如在每个 ID 的前面都加一个 HASH 值来提升查询性能。

  4. 列(column):,与关系型数据库中的列不同,HBase中的column由column family(列簇)以及qualifier(列名)两部分组成,两者中间使用":"相连。column family在表创建的时候需要指定,用户不能随意增减。一个column family下可以设置任意多个qualifier,因此可以理解为HBase中的列可以动态增加,理论上甚至可以扩展到上百万列。

  5. 列簇(Column Family):列簇是表中数据的物理存储单位,用于组织数据。列簇内的数据具有相同的列前缀,并且通常一起存储在同一个磁盘文件中。可以看作是一组列,实际上一个列簇的作用也是用来管理若干个列,优化查询速度。所以列簇的名字要尽量短,同时对于经常需要一起查询的列放在一个列簇下面。比如说对于用户信息,一个用户的静态属性(姓名、年龄、电话、地址等)可以放在一个列簇下面,动态属性(点赞、收藏、评论等)可以放在一个列簇下面。HBase表中的列簇需要预先定义,如果要新增列簇就要先停用这个表。

  6. 列名(Column Qualifier):是用于唯一标识列簇中具体列的标签。它与列簇一起组成列的完整标识。Qualifier可以动态地添加到列簇中,而无需预先定义,这使得HBase能够适应不同数据模式和需求的变化,而无需对表格的架构进行修改。

  7. 单元(Cell):指的是一个确定的存储单元。由五元组(row, column, timestamp, type, value)组成的结构,其中type表示 Put/Delete 这样的操作类型,timestamp代表这个cell的版本。这个结构在数据库中实际是以KV结构存储的,其中(row, column, timestamp,type)是K,value字段对应KV结构的V。单元格中的数据没有类型的概念,而是以字节序列的形式存储( 字符串正常存储,非字符串类型数据底层字节序列会转换成十六进制显示)。每个列簇中的列可以存储多个版本的数据,每个版本由其对应的时间戳标识,并且每个版本的值都构成一 个单元格。

  8. 时间戳(Timestamp):时间戳用于记录数据的创建或修改时间,并支持多版本数据。每个单元格(Cell)都可以存储多个版本的数据,版本通过时间戳来索引。

  9. 区域(Region):一个 Region 可以看作是多行数据的集合。当一个表的数据逐渐增多,需要进行分布式存储,那么这个表就会自动分裂成多个 Region,然后分配到不同的 RegionServer 上面去。

数据模型

既然HBase是一个数据库,那最核心的自然是怎么组织存储数据了,HBase的数据模型设计主要包括以下几个方面:

  1. 面向列的存储模型:HBase采用面向列的存储模型,表的基本单元是“列簇(Column Family)”。

  2. 数据多版本支持:HBase支持数据的多版本,每个单元格的数据可以有多个版本,版本通过时间戳来索引。

  3. 稀疏数据支持:HBase支持稀疏数据,即某些列可以为空,不会占用存储空间。

数据目录

HBase的数据目录主要包括以下几个方面:

  1. 根目录:HBase的根目录在HDFS中是/hbase,这是所有HBase数据的顶级目录。

  2. 数据目录:在根目录下,有一个名为/data的目录,它是HBase数据的核心存储区域,包含了所有的表数据、日志数据等。

  3. Namespace目录:HBase中的Namespace是用来组织和管理表的命名空间。在/data目录下,根据Namespace的不同,会有相应的子目录,例如/data/default

  4. 表目录:每个表在Namespace目录下都有一个对应的子目录,例如/data/default/mytable。这个目录下包含了该表的所有数据。

  5. Region目录:HBase中的表会被切分为多个Region,每个Region由一个或多个Store组成。每个Region在表目录下都有一个对应的子目录,例如/data/default/mytable/a3d605ed-33fe-4458-90ad-57c79989c730

  6. ColumnFamily目录:每个ColumnFamily在Region目录下都有一个对应的子目录,例如/data/default/mytable/a3d605ed-33fe-4458-90ad-57c79989c730/cf1。这个目录下包含了该ColumnFamily的所有数据。

为了更好理解HBase表存储结构,这里将HBase表存储结构分为表逻辑结构和表物理结构两个部 分介绍。

表逻辑结构

RowKey Column Family Column Family
Column Qualifier Column Qualifier Column Qualifier Column Qualifier
rowkey cell cell cell cell
rowkey cell cell cell cell
... ... ... ... ...

为了更清晰理解HBase表逻辑结构,填充样例数据如下(其中89c730对应的age为空):

RowKey staticattribute dynamicattribute
name age like favorites
57c799 chaos 18 hadoop hadoop
89c730 hbase zookeeper hdfs
... ... ... ... ...

表物理结构

在HBase中表数据存储并不是按照表逻辑结构进行存储,而是按照如下方式进行存储(以先前样例数据为例):

RowKey Column Family Column Qualifier Timestamp Value
57c799 staticattribute name 1000 chaos Region
57c799 staticattribute age 1000 18
57c799 dynamicattribute like 1000 hadoop
57c799 dynamicattribute favorites 1000 hadoop
89c730 staticattribute name 2000 hbase Region
89c730 dynamicattribute like 2000 zookeeper
89c730 dynamicattribute favorites 2000 hdfs

注意:在表逻辑结构中的空值在HBase底层不会进行存储。

HBase的物理存储结构设计主要包括以下几个方面:

  1. HDFS存储:HBase的数据最终存储在HDFS上,以HFile的形式存在。HFile是HBase的物理存储文件,以列簇为单位进行存储。

  2. Region:HBase通过Region来对表进行分片,每个Region负责存储某个RowKey范围内的行。当表中的数据增长到一定程度时,Region会被拆分为两个新的Region。

  3. Store:每个列簇对应一个Store,用于管理该列簇的数据。Store由内存中的MemStore和磁盘上的HFile组成。数据先写入MemStore,然后定期将MemStore中的数据刷到磁盘形成HFile。

  4. MemStore和HFile:MemStore是内存中的数据结构,用于缓存写入操作。当MemStore达到一定大小后,数据将被刷写到HFile中。HFile是磁盘上的物理存储文件,存储了列簇的数据。

架构设计

HBase建立在Hadoop HDFS之上,底层使用HDFS进行数据存储,HBase集群中主要由以下几个部分组成:

  1. Client:Client为访问HBase的客户端,包含访问HBase的接口并维护cache来加快对HBase的访问。Client通过zookeeper获取hbase:meta表位置信息,然后获取要操作的Region信息并与该 region的RegionServer通信,发出读取或写入请求。获取的Region信息会缓存在客户端中,以便后续请求无需经过查找过程。如果Master的负载均衡器重新平衡或者由于HRegionserver宕机,都会重新指定该region的 regionserver,客户端将重新查询hbase:meta表以确定用户region的新位置。

  2. HMaster:HMaster是HBase集群的主节点,负责管理RegionServer和Region的元数据、表的创建、分区的拆分和合并、Region的分配和迁移等任务。一个HBase集群中可以有多个 HMaster节点,由zk进行协调,保证只有一个HMaster运行,其余HMaster为Backup Master。

    1. 管理库表的元数据,如表对应Region信息,负责将Region分配给HRegionServer。

    2. 负责HRegionServer的负载均衡。当写入数据时负责将数据均衡的分布到各个Region上,避免HRegionServer数据存储倾斜;当读取数据时,将请求均衡的发送到各个RegionServer上,避免HRegionSever负载过大。

    3. 通过zk发现失效的HRegionServer并重新分配该HRegionServer上的Region。

  3. HRegionServer:HRegionServer可以看成HBase架构中的从节点,习惯上也可称为RegionServer,HBase集群中一般有多台HRegionServer,主要负责数据读写请求。
    一个HRegionServer包含一个HLog和多个HRegion,每个HRegion中有包含多个Store,每个 Store中又包含MemStore和StoreFile。

    1. 管理HMaster分配的Region,处理来自客户端的读写请求(如:put、get请求),定期向 HMaster汇报Region状态。

    2. 负责Region变大拆分。当一个Region的数据量增大到一定程度,HRegionServer负责将 Region拆分为两个新的Region,实现数据均衡分布。

    3. 负责StoreFile合并。

    4. 负责与HDFS交互,将数据存储到HDFS中。

  4. Zookeeper:HBase用Zookeeper进行分布式协调,帮助管理元数据、故障恢复和分布式锁。

    1. 存储HBase元数据,如:HMaster信息、HRegionServer信息、表对应HMaster信息、hbase: meta表位置信息。

    2. 协调HMaster的HA。通过zk保证HBase集群中只有一个HMaster运行,如果HMaster发生异常则通过zk选举新的HMaster提供服务。

    3. 监控RegionServer。zk监控RegionServer状态,当RegionServer异常时,会通知给HMaster 对应RegionServer上下线信息。

  5. HDFS:HBase底层使用HFile格式将数据存储在HDFS中,HDFS中数据多副本可以为HBase提供高可靠、高可用性。

优缺点

优点

  1. 高扩展性:HBase采用分布式架构,能够轻松扩展到数千个节点,处理PB级别的数据。

  2. 高性能:HBase在处理大规模数据时表现出色,特别是在随机读写操作方面。

  3. 高可靠性:HBase通过数据冗余和自动故障恢复机制,确保数据的高可用性和系统的稳定性。

  4. 灵活的数据模型:HBase支持动态列,可以根据需要随时增加新的列,而无需预先定义表结构。

  5. 面向列的存储:HBase采用面向列的存储模型,使得数据的读写操作更加高效,特别适合处理稀疏数据。

  6. 适用于实时数据处理:HBase特别适合于实时数据处理、海量数据存储和高速随机读写等应用场景。

缺点

  1. 数据模型的限制

    • 强烈的Schema依赖:HBase的数据模型是基于列簇和列的,这要求在设计表结构时就必须明确定义列簇和列。Schema的修改成本较高,需要进行表结构的重建或者复杂的在线调整,这会影响系统可用性和性能。

    • 缺乏丰富的查询功能:与关系型数据库相比,HBase的查询功能相对简陋。它主要支持基于行键的精确查找以及范围扫描,缺乏复杂的JOIN操作、聚合函数等功能。

    • 数据原子性:HBase的行是原子性的,但列不是。这意味着在一个事务中,你只能更新整行数据,而不能单独更新某一列。

  2. 性能方面的问题

    • 写性能瓶颈:虽然HBase的读写性能都相对较高,但在高并发写操作下,HBase的写性能可能会成为瓶颈。

    • 读性能瓶颈:当数据量非常大时,扫描大量数据可能会导致读性能下降。

    • 热点区域:不均匀的数据分布会导致某些Region Server负载过重,形成热点区域,从而影响整体性能。

  3. 可用性和维护性

    • 数据一致性:HBase采用最终一致性模型,这意味数据在不同节点之间的同步存在延迟。

    • 缺乏成熟的GUI工具:与一些关系型数据库相比,HBase缺乏成熟易用的GUI工具,这给数据的管理和监控带来不便。

    • 数据备份和恢复:HBase的数据备份和恢复也相对复杂,需要额外的工具和策略来保障数据的安全性和可靠性。


网站公告

今日签到

点亮在社区的每一天
去签到