概述
Hbase是一个分布式的存储系统。Hbase利用Hadoop的HDFS作为其文件存储系统,利用Hadoop的MapReduce来处理Hbase中的海量数据。利用zookeeper作为其协调工具。在Hadoop整个生态系统中的位置关系如下图:
特点
- 大:一个表的数据量可以很大,比如有数十亿行,百万列
- 无固定模式:每一行都有一个可排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有不同的列,因为表是稀疏的;
- 面向列:
- 稀疏性:空(null)列并不占用存储空间,表可以设计的非常稀疏。
- 数据的多版本:每个单元中的数据可以有多个版本,默认情况下版本自动为单元格数据插入时候的时间戳。
- 数据类型单一:HBase中的数据都是字符串,没有类型。
数据模型
基本概念
- 表(Table):表是在schema声明的时候定义的。
- 行(RowKey):行键是不可分割的字节数组。行是按字典排序由低到高存储在表中的。一个空的数组是用来标识表空间的起始或者结尾,方便快速查找,Rowkey的设计非常重要。
- 列族(Column Family):HBase中列族是一些列的集合。一个列族所有列成员是有着相同的前缀。比如,列courses:history 和 courses:math都是 列族 courses的成员.冒号(:)是列族的分隔符,用来区分前缀和列名。列族必须在表建立的时候声明。column就不需要了,随时可以新建。
- 列(Column)::属于某一个columnfamily,familyName:columnName,可动态添加。
- 版本号(Version Number):类型为Long,默认值是系统时间戳,可由用户自定义。
- 单元(Cell):Cell的内容是不可分割的字节数组。
整体的逻辑视图如下所示:
从逻辑上讲,HBase将数据按照表、行和列进行存储。为了更加直观的展示Hbase的逻辑存储,请看下图所示:
值得注意的是在上面的概念视图中空白cell在物理上是不存储的,因为根本没有必要存储。因此若一个请求为要获取t8时间的contents:html,他的结果就是空。相似的,若请求为获取t9时间的anchor:my.look.ca,结果也是空。但是,如果不指明时间,将会返回最新时间的行,每个最新的都会返回。例如,如果请求为获取行键为”com.cnn.www”,没有指明时间戳的话,活动的结果是t6下的contents:html,t9下的anchor:cnnsi.com和t8下anchor:my.look.ca。
物理视图
首先直观地看一下物理视图的存储,以上图中表5.1所示:
可以看出,存储上按照列族进行存储,且空白单元不存储。
- 每个column family存储在HDFS上的一个单独文件中,空值不会被保存。
- HBase 为每个值维护了多级索引,即:(key, column family, column name, timestamp)
物理存储:
- Table中所有行都按照row key的字典序排列;
- Table在行的方向上分割为多个Region;
- Region按大小分割的,每个表开始只有一个region,随着数据增多,region不断增大,当增大到一个阀值的时候,region就会等分会两个新的region,之后会有越来越多的region;
- Region是Hbase中分布式存储和负载均衡的最小单元,不同Region分布到不同RegionServer上。
此部分讲解具体存储概览看下图:
这里其实每个Region由[startkey,endkey) 表示,每个Region会被Master分散到不同的HRegionServer上面进行存储,类似于Hdfs的block块会被分散到不同的DataNode节点上面进行存储。借鉴一下大神的图进行展示:
- Region由一个或者多个Store组成,每个store保存一个columns family;每个Strore又由一个memStore和0至多个StoreFile组成,StoreFile包含HFile;memStore存储在内存中,StoreFile存储在HDFS上。具体视图如下:
Hbase体系架构及基本组件
下面介绍一下HBase的整体体系结构以及结构中的一些关键组件的作用,首先看一下官方结构图:
Client组件
- 包含访问HBase的接口,并维护cache来加快对HBase的访问,比如region的位置信息
HMaster组件
- HBase中存在多个Hmaster,但是同一时间只会有一个扮演者HMaster的角色,剩下的节点会在当前主节点发生故障时接管工作
- 负载均衡:不负责存储表数据,负责管理RegionServer的负载均衡(即防止某些RegionServer存储数据量大,有些 RegionServer存储数据量小),调整RegionServer上面Region的分布
- 管理RegionServer的状态,例如在HRegionServer宕机后,负责失效HRegionServer上Regions的迁移
- 在Region Split后,负责新Region的分配
HRegionServer服务器中存储了很多的HRegion,每个HRegion是由很多个HStore组成的,每个ColumnFamily就是一个HSore。
RegionServer组件
- Regionserver维护region,处理对这些region的IO请求,即负责响应用户向表中的读写操作,是Hbase体系结构中最核心的模块
- Regionserver负责切分在运行过程中变得过大的region
- HLog:存储了用户对表数据的最新的一些操作日志记录。下面需要介绍一下预写日志Write-Ahead-Log(WAL),该机制主要用于数据的容错与恢复,主要过程如下:
- 每个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,完成数据恢复。过程图如下图:
Zookeeper组件
- Hadoop的分布式协调服务组件,负责协调集群中的分布式组件
- 通过选举机制,可以保证任何时候,集群中只有一个Hmaster,Hmaster与HRegionServers 启动时会向ZooKeeper注册
- Zookeeper集群实时监控着HRegionServer这些服务器的状态,将HRegionServer的上线和下线信息实时通知给Hmaster节点,使得Hmaster节点可以随时感知各个HRegionServer的健康状态。
- Zookeeper集群中记录了-ROOT-表的位置
这里介绍一下Hbase中两张特殊的表:-ROOT-表与.META.表
-ROOT-表:记录了所有.META.表的元数据信息,-ROOT-表只有一个Region
.META.表:记录了Hbase中所有的用户空间region列表,以及RegionServer的服务器地址,.META.表可以有多个Region - Zookeeper的引入使得Master不再是单点故障
HBase寻址机制
Hbase在海量的表数据中,是如何找到用户所需要的表数据的呢?这里是通过索引的机制解决了这个问题。
如下图所示:
Client访问用户数据之前需要首先访问zookeeper集群,通过zookeeper集群首先确定-ROOT-表在的位置,然后在通过访问-ROOT- 表确定相应.META.表的位置,最后根据.META.中存储的相应元数据信息找到用户数据的位置去访问。通过 这种索引机制解决了复杂了寻址问题。
HBase使用场景
- 大数据量存储,大数据量高并发操作
- 需要对数据随机读写操作
- 读写访问均是非常简单的操作
与HDFS对比
- 两者都具有良好的容错性和扩展性,都可以扩展到成百上千个节点;
- HDFS适合批处理场景
- 不支持数据随机查找
- 不适合增量数据处理
- 不支持数据更新
参考文献