Fork me on GitHub

HBase入门

简介

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

面向可扩展性的分布式数据库,如hbase,与面向高性能并发读写的key-value数据库,如Redis,面向海量数据访问的文档数据库,如MongoDB共同构成的应用场景,是用于解决在当前互联网发展阶段产生的巨量数据分布式处理,大量非结构化数据处理,各种社交平台日常生活中产生的的文本信息处理的重要解决方案。

Hbase是什么

HBase 是 Google Bigtable 的开源实现,类似 Google Bigtable 利用 GFS 作为其文件存储系统,HBase 利用 Hadoop HDFS 作为其文件存储系统;Google运行 MapReduce 来处理 Bigtable 中的海量数据,HBase 利用 Hadoop MapReduce 来处理 HBase 中的海量数据;Google Bigtable 利用 Chubby 作为协同服务,HBase 利用 ookeeper 作为对应。

HBase 是一个分布式的、面向列的开源数据库,是 Apache 的 Hadoop 项目的子项目。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库,另一个不同是 HBase 基于列而不是基于行的模式。

如图,HBase 位于结构化存储层,Hadoop HDFS 为 HBase 提供了高可靠性的底层存储支持,Hadoop MapReduc 为 HBase 提供了高性能的计算能力,Zookeeper 为 HBase 提供了稳定服务和 failover 机制。

Pig 和 Hive 还为 HBase 提供了高层语言支持,使得在 HBase 上进行数据统计处理变的非常简单。 Sqoop 则为 HBase 提供了方便的 RDBMS 数据导入功能,使得传统数据库数据向 HBase 中迁移变的非常方便。

spark的构成

如何访问Hbase

1. Native Java API,最常规和高效的访问方式,适合Hadoop MapReduce Job并行批处理HBase表数据
2. HBase Shell,HBase的命令行工具,最简单的接口,适合HBase管理使用
3. Thrift Gateway,利用Thrift序列化技术,支持C++,PHP,Python等多种语言,适合其他异构系统在线访问HBase表数据
4. REST Gateway,支持REST 风格的Http API访问HBase, 解除了语言限制
5. Pig,可以使用Pig Latin流式编程语言来操作HBase中的数据,和Hive类似,本质最终也是编译成MapReduce Job来处理HBase表数据,适合做数据统计
6. Hive,当前Hive的Release版本尚没有加入对HBase的支持,但在下一个版本Hive 0.7.0中将会支持HBase,可以使用类似SQL语言来访问HBase

Hbase数据模型

HBase的特点

  1. 大:一个表可以有上亿行,上百万列。
  2. 面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
  3. 稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
  4. 无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列。
  5. 数据多版本:每个单元中的数据可以有多个版本,默认情况下,版本号自动分配,版本号就是单元格插入时的时间戳。
  6. 数据类型单一:HBase中的数据都是字符串,没有类型。

Table & Column Family

Row Key: 行键,Table的主键,Table中的记录按照Row Key排序
访问 HBase table 中的行,只有三种方式:

1)通过单个 Row Key 访问。

2)通过 Row Key 的 range 全表扫描。

3)Row Key 可以使任意字符串(最大长度是64KB,实际应用中长度一般为 10 ~ 100bytes),在HBase 内部,Row Key 保存为字节数组。

Timestamp: 时间戳,每次数据操作对应的时间戳,可以看作是数据的version number

Column Family:列簇,Table在水平方向有一个或者多个Column Family组成,一个Column Family中可以由任意多个Column组成,即Column Family支持动态扩展,无需预先定义Column的数量以及类型,所有Column均以二进制格式存储,用户需要自行进行类型转换。

逻辑数据模型中空白cell在物理上是不存储的,因为根本没有必要存储,因此若一个请求为要获取t8时间的contents:html,他的结果就是空。相似的,若请求为获取t9时间的anchor:my.look.ca,结果也是空。但是,如果不指明时间,将会返回最新时间的行,每个最新的都会返回

Table & Region

当Table随着记录数不断增加而变大后,会逐渐分裂成多份splits,成为regions,一个region由[startkey,endkey)表示,不同的region会被Master分配给相应的RegionServer进行管理

HBase中有两张特殊的Table,-ROOT-和.META.

.META.:记录了用户表的Region信息,.META.可以有多个regoin

-ROOT-:记录了.META.表的Region信息,-ROOT-只有一个region

Zookeeper中记录了-ROOT-表的location

MapReduce on HBase

在HBase系统上运行批处理运算,最方便和实用的模型依然是MapReduce,如图所示,HBase Table和Region的关系,比较类似HDFS File和Block的关系,HBase提供了配套的TableInputFormat和TableOutputFormat API,可以方便的将HBase Table作为Hadoop MapReduce的Source和Sink,对于MapReduce Job应用开发人员来说,基本不需要关注HBase系统自身的细节。

HBase系统架构

Client

HBase Client使用HBase的RPC(Remote Procedure Call – 远程过程调用)机制与HMaster和HRegionServer进行通信,对于管理类操作,Client与HMaster进行RPC;对于数据读写类操作,Client与HRegionServer进行RPC

Zookeeper

Zookeeper Quorum中除了存储了-ROOT-表的地址和HMaster的地址,HRegionServer也会把自己以Ephemeral方式注册到 Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的健康状态。此外,Zookeeper也避免了HMaster的 单点问题

HMaster

HMaster没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行,HMaster在功能上主要负责Table和Region的管理工作:

1.管理用户对Table的增、删、改、查操作

2.管理HRegionServer的负载均衡,调整Region分布

3.在Region Split后,负责新Region的分配

4.在HRegionServer停机后,负责失效HRegionServer 上的Regions迁移

HRegionServer

HRegionServer主要负责响应用户I/O请求,向HDFS文件系统中读写数据,是HBase中最核心的模块。

如图,HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,HRegion中由多个HStore组成。每个HStore对应了Table中的一个Column Family的存储,可以看出每个Column Family其实就是一个集中的存储单元

HStore存储是HBase存储的核心,由两部分组成,一部分是MemStore,一部分是StoreFiles,MemStore是 Sorted Memory Buffer,用户写入的数据首先会放入MemStore,当MemStore满了以后会Flush成一个StoreFile(底层实现是HFile), 当StoreFile文件数量增长到一定阈值,会触发Compact合并操作,将多个StoreFiles合并成一个StoreFile,合并过程中会进 行版本合并和数据删除,因此可以看出HBase其实只有增加数据,所有的更新和删除操作都是在后续的compact过程中进行的,这使得用户的写操作只要 进入内存中就可以立即返回,保证了HBase I/O的高性能。当StoreFiles Compact后,会逐步形成越来越大的StoreFile,当单个StoreFile大小超过一定阈值后,会触发Split操作,同时把当前 Region Split成2个Region,父Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer 上,使得原先1个Region的压力得以分流到2个Region上。

在理解了上述HStore的基本原理后,还必须了解一下HLog的功能,因为上述的HStore在系统正常工作的前提下是没有问题的,但是在分布式 系统环境中,无法避免系统出错或者宕机,因此一旦HRegionServer意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。 每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中(HLog文件格式见后续),HLog文件定期会滚动出新的,并 删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知 到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。

HBase存储格式

HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括上述提出的两种文件类型:

1.HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile

2.HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File

HFile

如图HFile的存储格式,首先HFile是不定长的,长度固定的只有其中两块:Trailer和Fileinfo。

Trailer中有指针指向其他数据块的起始点;
Fileinfo则记录了文件的部分meta信息,如AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等;
Data Index和Meta Index块记录了每个Data块和Meta块的起始点。

Data Block是HBase I/O的基本单元,为了提高效率,HRegionServer中有基于LRU的Block Cache机制。每个Data块的大小可以在创建一个Table的时候通过参数指定,大号的Block有利于顺序Scan,小号Block利于随机查询。 每个Data块除了开头的Magic以外就是一个个KeyValue对拼接而成, Magic内容就是一些随机数字,目的是防止数据损坏。后面会详细介绍每个KeyValue对的内部构造。

LRU:Least Recently Used ,内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。

HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。具体结构如图:开始时两个固定长度的数值,分别表示key的长度和value的长度,紧接着是key,开始是固定长度的数值,表示rowkey的长度,紧接着是rowkey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据。

HLogFile

如图是HLog文件的结构,其实HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是“写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。

HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue

HBase的高并发和实时处理数据

Hadoop是一个高容错、高延时的分布式文件系统和高并发的批处理系统,不适用于提供实时计算;HBase是可以提供实时计算的分布式数据库,数据被保存在HDFS分布式文件系统上,由HDFS保证其高容错性。

在生产环境中,HBase是如何基于hadoop提供实时性呢?

HBase上的数据是以StoreFile(HFile)二进制流的形式存储在HDFS上block块儿中;但是HDFS并不知道的HBase存的是什么,它只把存储文件视为二进制文件,也就是说,HBase的存储数据对于HDFS文件系统是透明的。

从根本上说,HBase能提供实时计算服务主要原因是由其架构和底层的数据结构决定的,即由LSM-Tree + HTable(region分区) + Cache决定——客户端可以直接定位到要查数据所在的HRegion server服务器,然后直接在服务器的一个region上查找要匹配的数据,并且这些数据部分是经过cache缓存的。

具体数据访问流程如下:

1. Client会通过内部缓存的相关的-ROOT-中的信息和.META.中的信息直接连接与请求数据匹配的HRegion server;
2. 然后直接定位到该服务器上与客户请求对应的Region,客户请求首先会查询该Region在内存中的缓存——Memstore(Memstore是一个按key排序的树形结构的缓冲区);
3. 如果在Memstore中查到结果则直接将结果返回给Client;
4. 在Memstore中没有查到匹配的数据,接下来会读已持久化的StoreFile文件中的数据,StoreFile也是按 key排序的树形结构的文件——并且是特别为范围查询或block查询优化过的,HBase读取磁盘文件是按其基本I/O单元(即 HBase Block)读数据的。

hbase的具体配置使用跟hadoop,spark有密切关系,后面会有专门的博客来介绍openstack和hadoop,包括原理和配置,那里面会包含hbase的安装配置使用方法,这个坑交给后面的文章来填,就这么愉快得决定了!