Hbase理论入门


1 概念

HBase是Apache的Hadoop项目的子项目,是Hadoop Database的简称。构建在 Apache Hadoop和 Apache ZooKeeper之上。

一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价的机器上搭建起大规模结构化存储集群。

HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。

特点:

  • 海量存储:HBase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。这与HBase的记忆扩展性息息相关。正是因为HBase的良好扩展性,才为海量数据的存储提供了便利。
  • 列式存储:列式存储,HBase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定,而不用指定列。
  • 极易扩展:HBase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储能力(HDFS)的扩展。
  • 高并发:目前大部分使用HBase的架构,都是采用廉价PC,因此单个IO的延迟其实并不小,一般在几十到上百ms之间。这里说的高并发,主要是在并发的情况下,HBase的单个IO延迟下降并不多。
  • 稀疏:稀疏主要是针对HBase列的灵活性,在列族中,可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间

概括:

  1. HBase底层存储并非必须是HDFS文件系统,但是HDFS是最佳选择
  2. 该技术来源于Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力
  3. 一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。Hbase参考了谷歌的BigTable建模,使用HDFS作为底层存储,使用Zookeeper作为协同服务组件。
  4. 安装Hbase必须安装jdk,Hbase是Java编写

2 数据模型

  • Namespace(表命名空间):表命名空间不是强制的,如果想把多个表分到一个组去统一管理的时候才会用到表命名空间。

  • Table(表):一个表由多行组成。

  • Row(行):一个行键和一个或多个列组成

  • Column Family(列族):列族是多个列的集合。

  • Column Qualifier(列):列由 列族列限定符组成,列是可以随意定义的,一个行中的列不限名字,不限数量,只限定列族。

    如:

    content:pdf

    content是列族,pdf是列限定符。

  • Cell(单元格):单元格是行,列族和列限定符的组合,它包含一个值和一个时间戳,时间戳表示值的版本。

  • Timestamp(时间戳/版本号):用来标定同一个列中多个Cell的版本号。当在插入数据的时候,如果不指定版本号,系统会自动采用系统的当前时间戳来作为版本号,也可以手动指定一个数字作为版本号。

  • Rowkey(行键):用来标识表中唯一的一行数据,以字节数组形式存储,类似关系型数据库中表的主键。rowkey在HBase中时严格按照字典序排序的

image-20201111162945221


image-20201111163541421

image-20201111164540933

时间戳按降序存储,取模个cell的值默认取版本最新的值。取列中不存在的值将不返回任何值

3 架构

image-20201111172040908

3.1 主从结构

Master:

  1. 负责RegionServer的Region分配和负载均衡。
  2. 发现失效的RegionServer并重新分配Region;
  3. 处理Schema更新请求(表的创建、删除、修改、列族的增加等)。
  4. 管理namespace和table的元数据(实际存储在HDFS上)。

RegionServer:

  1. 存放和管理本地Region。
  2. 读写HDFS,管理Table中的数据。
  3. 处理Client的IO请求(Client从Master中获取元数据,找到RowKey所在的Region/RegionServer后,类HDFS)。
  4. 负责region的切分和合并
  1. HDFS
  • 为HBase提供最终的底层数据存储服务(包括元数据和表数据)
  • 同时为HBase提供高可用(HLog)的支持
  1. Zookeeper
  • 为HBase提供Failover机制,选举master,避免master单点故障问题;
  • 存储所有Region的寻址入口,保存hbase:meta表信息;
  • 实时监控RegionServer的状态,将RegionServer的上线和下线信息实时通知给master;
  • 存储HBase的Schema,包括有哪些Table,每个Table有哪些Column Family
  1. Client

    Client使用HBase的RPC机制与HMaster、RegionServer进行通信,Client与Master进行管理类通信,与RegionServer进行数据操作类通信。Client包含了访问HBase的接口,另外Client还维护了对应的cache来加速HBase的访问,

3.2 RegionServer结构

image-20201111174323169

  1. region, 可以理解为一张表或者一张表的横向切分后的一段,Hbase会自动将表切分成多个region, 初始时一张表只有一个region。

  2. 一个region包含某些Strore, 一个store就相当于一个列族

  3. 一个列族里面有一个Memstore和零个或多个StoreFile,当写入数据时,首先写入MemStore中(先这样理解),当Memstore中的数据达到一定程度时,会flush到一个Storefile(存储在Hfile)

  4. 当一个Strore中的Storefile数量达到一定程度时,就会进行StoreFile的合并操作。

  5. 当region中总的StoreFile达到一定体量后,便会触发切分region的操作。将region切分成两个子region,然后由HMaster根据负载情况分配到HRegionServer中。

  6. WAL预写日志,在将数据写入MemStore前,会先写入WAL中,再进行前面的第二部操作。这样的好处是当Region所在的机器宕机后,可以从WAL中恢复数据。(在写入MemStore中会对数据根据rowKey进行排序操作)

  7. BlockCache,读缓存,用于在内存中缓存经常被读的数据。Least Recently Used (LRU) 数据在存满时会被失效。

4 原理

4.1 region合并

4.1.1 小合并(Minor Compaction)

当MemStore达到hbase.hregion.memstore.flush.size大小的时候会将数据刷写到磁盘,生成StoreFile。随着业务的发展,数据量会越来越大,会产生很多的小文件,对于HBase的数据读取,如果要扫描大量的小文件,会导致性能很差,因此需要将这些小文件合并成一个大一点的文件。

小合并,就是把多个小的StoreFile组合在一起,形成一个较大的StoreFile,步骤如下:

  1. 分别读取出待合并的StoreFile文件的KeyValues,并顺序地写入到位于/hbase/.tmp目录下的临时文件中;
  2. 将临时文件移动到对应的Region目录中;
  3. 将合并的输入文件路径和输出路径封装成KeyValues写入WAL日志,并打上compaction标记,最后强制执行sync;
  4. 将对应region数据目录下的合并的输入文件全部删除,合并完成。

小合并一般速度比较快,对业务的影响也比较小。本质上,小合并就是使用短时间的IO消耗以及带宽消耗换取后续查询的低延迟。在Minor Compaction过程中,达到TTL(记录保留时间)的数据会被移除,但是由墓碑标记的记录不会被移除,因为墓碑标记可能存储在不同HFile中,合并可能会跨过部分墓碑标记。

4.1.2 大合并(Major Compation)

大合并就是将一个Region下的所有StoreFile合并成一个大的StoreFile文件。在大合并的过程中,之前删除的行和过期的版本都会被删除。大合并一般一周做一次,由hbase.hregion.majorcompaction参数控制。大合并的影响一般比较大,尽量避免同一时间多个Region进行合并,因此HBase通过hbase.hregion.majorcompaction.jitter参数来进行控制,用于防止多个Region同时进行大合并。

具体算法:

hbase.hregion.majorcompaction参数的值乘以一个随机分数,这个随机分数不能超过hbase.hregion.majorcompation.jitter的值(默认为0.5)。

通过hbase.hregion.majorcompaction参数的值加上或减去hbase.hregion.majorcompaction参数的值乘以一个随机分数的值就确定下一次大合并的时间区间。

可以通过hbase.hregion.majorcompaction设置为0来禁用major compaction。

4.2 Client-Server交互逻辑

  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发送真正的数据读取请求。服务器端接收到该请求之后需要进行复杂的处理,具体的处理流程将会是这个专题的重点。
  1. 客户端只需要配置zookeeper的访问地址以及根目录,就可以进行正常的读写请求。不需要配置集群的RegionServer地址列表。
  2. 客户端会将hbase:meta元数据表缓存在本地,因此上述步骤中前两步只会在客户端第一次请求的时候发生,之后所有请求都直接从缓存中加载元数据。如果集群发生某些变化导致hbase:meta元数据更改,客户端再根据本地元数据表请求的时候就会发生异常,此时客户端需要重新加载一份最新的元数据表到本地。

region寻址步骤

  1. Client向zookeeper获取存储元数据的 hbass:meta 表 所在的 RegionServer A
  2. 连接 RegionServer A,将habse:meta表缓存到本地,根据rowKey获取region,根据region获取存取该region的 RegionServer B

4.3 Hbase写流程

image-20201111192308660

  1. Client进行region寻址得到ReionServer的信息
  2. Client连接RegionServer并发起 put请求
  3. 写入WHL,写入HLog,写入MemStore中
  4. 向Client反馈信息
  5. 判断MemSrore中的量是否达到 flush成为一个StoreFile 的阈值

写入Hlog的目的

在这个过程中系统会在Zookeeper中记录一个checkpoint,表示这个时刻之前的更新已经持久化了,当系统出现意外时,可能导致MemStore中的数据丢失,此时使用HLog来恢复chckpoint之后的数据。

在对HBase进行写操作的时候,进行Put和Update操作的时候,其实是新增了一条数据,即使是在进行Delete操作的时候,也是新增一条数据,只是这条数据没有value,类型为DELETE,这条数据叫做墓碑标记(Tobstone)。数据的真正删除是在compact操作时进行的。

4.4 Hbase读流程

image-20201111192732741

  1. Client进行region寻址得到ReionServer的信息
  2. Client连接RegionServer并发起 get 请求
  3. 先从BlockCache中查找数据,找不到再去MemStoreStoreFile中查询数据

4.5 RegionServer故障恢复

心跳机制:

在Zookeeper中保存着RegionServer的相关信息,在RegionServer启动的时候,会在Zookeeper中创建对应的临时节点。RegionServer通过Socket和Zookeeper建立session会话,RegionServer会周期性的向Zookeeper发送ping消息包,以此说明自己还处于存活状态。而Zookeeper收到ping包后,则会更新对应Session的超时时间。

当Zookeeper session超时时间还未收到RegionServer的ping包,则Zookeeper会认为该RegionServer出现故障,Zookeeper会将该RegionServer对应的临时节点删除出,并通知Master,Master收到RegionServer挂掉的信息后就会启动数据恢复流程。

5 参考

  1. Hbase 入门知识点总结

  2. HBase快速入门

  3. HBase 的行、列模型


作者: jdi146
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 jdi146 !
评论
评论
  目录