HBase实现了BigTable存储架构,是分布式的、可伸缩的数据库,适合存储非关系型的数据。Hbase的数据存储在HDFS,hbase和Hadoop之间的无缝集成保障了数据的可靠性(多个副本)。
相比于用hdfs来存放小文件,使用hbase来存储小文件更适合!因为——HBase中存储的记录,每一条的size在几百Bytes到Kb之间,如果将这些记录直接存储于HDFS之上会导致大量的小文件产生, 而每一个小文件都要有各自的元数据信息, 元数据是由HDFS的元数据管理节点(NameNode)负责的, 所以大量的小文件会给name node带来过大的负担;而使用hbase来存放小文件,那么这些小文件会由hbase合并(compact)成为更大的文件,这样就避免了小文件存放在HDFS上导致的元数据管理开销。
如果数据存储需要更多的空间,只需要在hbase集群中加入新的HRegionServer节点即可,HBase会自动水平切分扩展,所以能承载“十亿行、百万列”的数据规模。
Hbase数据库中表的存储,基本单位是列(column)。 一列或多列形成一行(row),并且有唯一的行健(row key)来确定存储。Hbase不支持二次索引,只支持行健索引,而且行健是有序的。
下面对HBase架构中的各个角色及其功能做简要介绍。
Zookeeper
hbase集群需要借助zookeeper,zookeeper会自动从Hbase集群中启动HMaster的多个节点中选出一个HMaster作为Active Master对外提供服务, 其余的作为Backup Master;另外,hbase集群中的各个节点的状态信息注册到zookeeper中以后,HMaster就能在zk中相应deznode随时感知各个HRegionServer的健康状态。
HMaster
HMaster的功能(作用):建表/修改表/删除表等DDL操作请求的服务端执行主体;监控所有HRegionServer的运行状态;管理所有的HRegionServer, 为每个HRegionServer分配HRegion。一般是配置两个HMaster,其中一个是active状态的master, 另一个是backup状态(备机),只有active状态的master才有管理功能。到底是主角色还是备机角色,是由ZooKeeper的选举机制来实现。
当HMaster感知到一个新的HRegionServer上线时,HMaster会告诉这个新的HRegionServer等待分配数据;当某个HRegionServer宕机时HMaster会把这个HRegionServer原先负责的所有HRegion标记为“未分配”,再把它们分配到其他HRegionServer中。具体的分配计划是由LoadBalancer来提供的:Master中有一个定时运行的线程,来检查集群中的Regions在各个RegionServer之间的负载是否是均衡。如果不均衡则通过LoadBalancer生成相应的Region迁移计划。用户也可以自定义负载均衡算法。
backup master的作用:可以通过一个client端的DDL操作来说明:例如客户端发来的建表请求,在执行过程中active master死掉了怎么办?那么backup master会接管服务,变成新的active master继续完成整个建表操作。
HRegionServer
HRegionServer是HBase中的核心模块,是Hbase的数据服务节点。它负责为客户端提供读、写请求,以及维护HRegion。一般来说hbase集群的每个节点只运行一个HRegionServer。此HRegionServer一般是和DataNode运行在同一个节点上,以便实现数据的本地化、避免不必要的网络I/O。每个HRegionServer维护HRegion的数量可以是多个,每个HRegion对应了逻辑表中的一个连续数据段。
HRegion
从逻辑上说,HBASE中的每张表可以理解成是行(记录)的集合,行是列族的集合,列族是列的集合。表的每一条记录根据行键(RowKey)来区分。从物理上来说,一张表被拆分成了若干个“分片”,每一个分片就是一个HRegion,也就是“区域”。
当一个表的大小超过预设值的时候,HBase会自动将这个表划分为不同的区域,每个区域包含此表所有记录中的一个子集。一个区域会保存此表中某段连续的数据,所以一张表的所有数据是存放在多个区域中的。我们用“表名+开始/结束行键”来区分每一个HRegion。
HRegion由多个HStore组成,每个HStore对应了逻辑表中的一个列簇的存储。
HStore
HStore是HBase存储的核心,由MemStore和StoreFiles两部分组成。
MemStore是内存缓冲区,用户写入的数据在写入WAL之后会马上放入MemStore,当MemStore满了以后会Flush成一个StoreFile(在HDFS底层的实现是HFile),当StoreFile的文件数量增长到一定阈值后,会触发minor compact合并操作,将多个StoreFiles合并成一个更大的StoreFile,合并过程中会进行版本合并和数据删除操作。实际上HBase只有增加数据,所有的更新和删除操作都在Compact过程中进行,所以客户端的写操作只要进到内存就能立即返回,保证了HBase的高性能I/O。
当StoreFiles做了若干次的minor compact后,会生成越来越大的StoreFile,当单个StoreFile的size超过临界值后触发Split操作:把当前的HRegion切成2个HRegion,原来的HRegion会下线,新切出来的2个HRegion会被HMaster分配到相应的HRegionServer,那么原来1个HRegion的负载就分摊到2个HRegion上,这样就能实现负载均衡。
HLog
每个HRegionServer中都有一个HLog对象,它是一个实现了Write Ahead Log的预写日志类。在每次用户操作将数据写入MemStore之前,会先写一份数据到HLog文件中。HLog文件会定期滚动刷新,并删除旧的文件(已持久化到StoreFile中的数据)。
Hbase的数据恢复就是由这个HLog参与实现的,数据恢复的原理是:当HMaster通过Zookeeper感知到某个HRegionServer意外宕机时,HMaster首先会处理宕机这台主机遗留的 HLog文件,将其中不同HRegion的HLog数据进行拆分,拆分后分别放到相应HRegion的目录下,然后再将失效的HRegion重新分配给其他HRegionServer节点上,领取到这些HRegion的HRegionServer在加载 HRegion的过程中会发现有历史HLog需要处理,那么会重新运算(Replay)这些历史HLog,产生的数据再放到MemStore中,最后Flush到StoreFiles,完成数据恢复。
HFile
HFile是数据的持久化文件,它位于HDFS。HFile里面是按照Key-Value格式存储数据的,同一个列族的所有列存储在同一个底层存储文件里。Hbase的数据在HDFS中的路径结构如下:
hdfs://your_host_url:8020{hbase.rootdir}/${名称空间}/${表名}/${区域名称}/${列族名称}/${文件名}
举例:{hbase.rootdir}/my_namespace/mytable/a4d63a61a8da24a863bff3c8d7cd20de/cf_name/c2a7fa8c41304b9e9b8b24b4a89171ce
其中 {区域名称} 是 mytable表的 region, 由每张表在水平方向上切割而成,所以一张表由若干个region组成,不同的region分配到不同的RegionServer以均衡负载。
Namespace
名称空间,类似关系型数据库系统中的“库”。每个namespace下可以建多个表。
Client
客户端程序。客户端使用HBase的RPC机制与HMaster和HRegionServer通信、提交读/写请求和获取结果。
对于管理类操作(例如创建新表),Client与HMaster进行RPC通信;数据读/写类操作,Client与HRegionServer进行RPC通信。