HBase是一种分布式的、面向列的开源NoSQL数据库。根据官方的说明,其更像是一个数据存储而非数据库,因为其缺失很多数据库的特性。但是其自身又有区别于传统数据库的强大特性,如:
强一致性读写,很适合高速计数聚合类任务;
HBase 表通过region被分发在集群中。并且随着数据增长,region会自动切分和重新分发;
RegionServer自动故障转移;
支持HDFS作为它的分布式文件系统;
通过MapReduce支持大规模并行处理,并且HBase 可以同时做源端和目标端;
支持Java API、Thrift/REST API;
在支持Block Cache and Bloom Filters作为大容量查询优化;
提供内置网页用于运维视角和JMX 度量。
综上,让我们来看下HBase包含哪些组件吧。
系统架构图

注意:有些图片上会把HLog画到Region中,但其实是每一个 RegionServer 就只有一个 HLog,而不是一个 Region 有一个 HLog。
从HBase的架构图上可以看出,HBase中的组件包括Client、Zookeeper、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog等,接下来我们依次介绍他们的作用。
Client
包含访问HBase的接口,并维护cache来加快对HBase的访问;
HBase集群的访问入口,通过RPC方式和HMaster、HRegionServer通信;
与HMaster进行通信进行管理表的操作, 与HRegionServer进行数据读写类操作。
Zookeeper
提供 Failover机制,保证任何时候,集群中只有一个HMaster;
实时监控HRegionServer的上线和下线信息,并实时通知给HMaster;
存储-ROOT-表地址(0.96版本之前,0.96版本后存储了.meta.表)、HMaster地址,HBase的schema和table元数据。
HMaster
HMaster维护表和HRegion的元数据
负责HRegionServer的负载均衡,调整HRegion分布,负责失效HRegionServer上的HRegion迁移工作;
管理用户对Table表的增、删、改、查操作;
HDFS上的垃圾文件回收。
HRegionServer
维护HRegion,处理HRegion的IO请求;
对运行中过大的HRegion进行split;
负责定期和阈值触发的Compact 操作,清理不需要的数据,控制HRegion的规模。
HRegion
HRegion是HBase中分布式存储和负载均衡的最小单元;
不同的HRegion可以分别在不同的HRegionServer上,同一个HRegion不会拆分到多个server上;
HRegion按大小分隔,每个表一般是只有一个HRegion,当HRegion的某个列族达到一个阈值(默认256M)就会分成两个新的HRegion,HRegion被分配给哪个HRegionServer是完全动态透明的;
每个HRegion由以下信息标识:< 表名,startRowkey,创建时间>,由目录表(-ROOT-和.META.)记录该HRegion的endRowkey 。
Store
每个HRegion至少由一个Store组成;
HBase会把一起访问的数据放在一个Store里面,即每个ColumnFamily建一个Store;
一个Store由一个memStore和若干StoreFile(也可为0)组成,HBase以Store的大小来判断是否需要切分HRegion。
MemStore
memStore 是放在内存里的,其保存修改的数据即Key-Values;
当memStore的大小达到一个阀值(默认128MB)时,memStore会被flush到文件,即生成一个快照。
StoreFile
memStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存在HDFS上;
StoreFile文件的数量增长到一定阈值后,系统会进行合并(minor/major compaction),在合并过程中会进行版本合并和删除工作,形成更大的StoreFile。
HFile
StoreFile对Hfile做了轻量级包装,StoreFile底层就是HFile;
HBase中Key-Value数据的存储格式,HFile是Hadoop的二进制格式文件。
HLog
HLog->WAL log-Write Ahead Log,数据的所有变更均会写入HLog,一旦HRegionServer 宕机,就可以从log中进行恢复;
HLog文件就是一个Hadoop Sequence File ,其中value是HBase的Key-Value对象,即对应HFile中的Key-Value,除此之外还记录了数据的归属信息,除了table和region名字外,还同时包括sequence number和写入时间timestamp。
HBase数据读写过程
初步了解了HBase的基础组件架构组成,接下来通过HBase实际的使用过程来串联其各组件的功能特性。
--HBase数据读请求
0.96版本之前:Client–>Zookeeper–>-ROOT-表–>.META.表–>HRegion–>HRegionServer–>Client
1)Client访问Zookeeper,查找-ROOT-表,获取.META.表信息(两种表均存储在HRS上,此处Client会缓存两张表的相关信息,并于下次使用);
2)从.META.表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer;
3)联系 RegionServer 定位到目标数据所在的Region,发出查询请求;
4)读请求先到MemStore中查数据,查不到就到BlockCache中查,命中即返回;
5)如果找不到,则在 Storefile 中扫描,并把读的结果放入BlockCache。
0.96版本后(新增了namespace,删去了-ROOT-表):Client–>Zookeeper–>.META.表–>HRegion–>HRegionServer–>Client
1)Client访问Zookeeper,获取.META.表信息(表存储在HRS上,此处Client会表的相关信息,并于下次使用,并且不会更新,只有当请求错误就会重新获取);
2)从.META.表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer;
3)联系 RegionServer 定位到目标数据所在的Region,发出查询请求;
4)读请求先到MemStore中查数据,查不到就到BlockCache中查,命中即返回;
5)如果找不到,则在 Storefile 中扫描,并把读的结果放入BlockCache。
去掉-ROOT-的原因:
其一:提高性能
其二:2 层结构已经足以满足集群的需求
--HBase数据写请求
1)Client向zookeeper获取.meta.表的HRegion信息,然后找到meta表的数据;
2)根据RowKey、.meta.表等信息找到对应的HRegion 所在的HRegionServe;
3)Client 向HRegionServer提交写请求;
4)将更新先写入HLog,紧接着写入Memstore;
5)数据到MemStore达到预设阈值,MemStore中的数据被Flush成一个StoreFile;
6)StoreFile不断增长到一定阈值后,触发Compact合并操作,将多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除;
7)单个StoreFile大小超过一定阈值后,触发Split操作,把当前HRegion离线Split成2个新的HRegion。