- HBase的数据模型与传统数据库相比更加灵活,使用之前无须预先定义一个所谓的表模式(schema),同一个表中不同行数据可以包含不同的列,而且HBase对列的数量并没有限制。当然如果一行包括太多的列,就会对性能产生负面影响。HBase很适合存储不确定列、不确定大小的半结构化数据。
一、逻辑模型
HBase是一个键值型数据库。HBase数据行可以类比成一个多重映射(map),通过多重的键一层层递进可以定位一个值(value)。因为HBase数据行列值可以是空白的(这些空白列是不占用存储空间的),所以HBase存储的数据是稀疏的。
HBase逻辑模型相关的术语
表(table):数据行的集合,表名用字符串表示,一个表可以包含一个或者多个分区(region)。
行键(row key):用来表示表中唯一的一行数据,以字节数组形式存储,行键并不能唯一标识一行数据,因为HBase数据行可以有多个版本,但是,一般在不指定版本或者数据时间戳的情况下,用行键可以获取到当前最新生效的这行数据,因此从用户视图来说,默认情况下行键能够标识唯一一行数据。同时行键也是HBase表中最直接最高效的索引,表中数据按行键的字典序排列。
列簇(column family):HBase是一个列式存储数据库,所谓列式就是根据列簇存储,每个列簇就是一个存储仓库(store),每个store有多个存储文件(storefile)用来存储实际数据。
列限定符(column qualifier):每个列簇可以有任意个列限定符用来标识不同的列,与传统数据库不同的是列无须在表创建时指定,可以在需要使用时动态加入。
单元格(cell):单元格由行键、列簇、列限定符、时间戳、类型(用来标识数据是有效还是删除状态)唯一决定,是HBase数据的存储单元,以字节码的形式存储。
版本(version):HBase数据写入后是不会被修改的,数据的Put等操作在写入预写入日志(WAL)后,会先写入内存仓库(MemStore),同时在内存中按行键排序,等到合适的时候会将MemStore中的数据刷新到磁盘的StoreFile文件。因为数据不会修改,因此带来的问题就是数据会有多个版本,这些数据都会有一个时间戳用来标识数据的写入时间。
分区(region):分区是集群中高可用、动态扩展、负载均衡的最小单元,一个表可以分为任意个分区并且均衡分布在集群中的每台机器上,分区按行键分片,可以在创建表的时候预先分片,也可以在之后需要的时候调用HBase shell命令行或API动态分片。
二、物理模型
物理存储模型
- HBase是一个列式存储数据库,数据按列簇存储在StoreFile中,空白的列单元格不会被存储。
- HBase中表按照行键的范围被划分为不同的分区(region),各个分区由分区服务器负责管理并提供数据读写服务,HBase主节点进程(HMaster)负责分区的分配以及在集群中的迁移。
- 一个分区同时有且仅有一个分区服务器提供服务(否则无法保证数据的一致性)。当分区增长到配置的大小后,则分区服务器会负责将这个分区拆分成两个。每个分区都有一个唯一的分区名,格式是“<表名,startRowKey,创建时间>”。一个分区下的每个列簇都会有一个存储仓库(Store),因此一个表有几个列簇,那么每个分区就会有几个Store。
- 每个Store有且仅有一个MemStore,但是可以有多个存储文件。当分区服务器处理写入请求时,数据的变更操作在写入WAL后,会先写入MemStore,同时在内存中按行键排序。当MemStore到达配置的大小或者集群中所有MemStore使用的总内存达到配置的阀值百分比时,MemStore会刷新一个StoreFile到磁盘,存储文件只会顺序写入,不支持修改。
- 数据块是HBase中数据读取的最小单位,StoreFile由数据块组成,可以在建表时按列簇指定表数据的数据块大小。如果开启了HBase的数据压缩功能,数据在写入StoreFile之前会按数据块进行压缩,读取时同样对数据块解压后再放入缓存。理想情况下,每次读取数据的大小都是指定的数据块大小的倍数,这样可以避免一些无效的IO,效率最高。
HBase进程概述
- HMaster:负责监控集群中所有的分区节点进程(HRegionServer)。负责所有元数据的更新(如分区由哪个分区节点提供服务)。HMaster同时负责分区在分区节点中的负载均衡,在一个分布式集群中,HMaster进程通常与NameNode运行在同一个节点上,每个集群会部署至少两个HMaster节点,一个作为活跃节点提供服务,另一个作为备用节点提供快速的灾备切换,保证集群的高可用(HA模式)。
- HRegionServer:管理其负责的分区,处理分区的读写请求、分区增大的拆分(split)以及分区的压缩(compact)。HBase客户端根据元数据(客户端从HMaster获取到元数据后会缓存在本地,当本地操作抛出特定异常后会从HMaster刷新缓存)定位到操作数据对应的分区所在分区服务器后,HBase客户端对数据的读写就直接与分区服务器交互,因此对分区的读写不会对HMaster造成压力。HRegionServer进程通常与DataNode运行在同一节点,这样对数据的读取可以尽量做到本地读取,减少网络请求。
- WAL:默认情况下每个HRegionServer仅有一个WAL,后期版本可以开启MutiWAL功能,允许多个WAL,且每个WAL是多个HRegion共享的。HBase客户端数据请求操作会先写入WAL文件再写入MemStore,这样当分区节点宕机重启时,可以用WAL来恢复分区服务器的状态(如MemStore中更新的数据没有刷新到StoreFile持久化,则分区节点启动时需要通过WAL重做(replay)数据更新来恢复)。如果数据操作写入WAL失败,则这个更新数据的请求也会失败。在WAL中,日志单元WALEntry(WAL的组成单元)表示一次行级更新的最小追加单元,它由HLogKey和WALEdit组成,WALEdit用来表示一个事务中的更新集合,HBase将一个行级事务的写入操作表示为一条记录以保证事务的原子性。
- Store:每个分区的每个列簇对应一个Store,一个Store包含一个MemStore和多个存储文件。当MemStore的大小达到了配置的阀值后,MemStore会刷新为一个存储文件,存储文件顺序写入,不支持修改,以HFile的形式存储在DataNode中。
- MemStore:MemStore位于分区节点的堆内存,数据在写入MemStore的时候即会按行键排序,这样刷新到存储文件的时候可以直接顺序写入,提供写性能。同时MemStore作为一个内存级缓存,能够提供对新写入数据的快速访问。