注:由图可见Hyperbase存储数据十分稀疏,在数据存储的时候,如果某一个单元格没有数据时,最终落在底层数据存储时也不会占据多余的存储空间。 同一单元格里的数据是按照时间倒叙排列,方便快速查找到最新的数据。rowkey有序的按照生序的方式排列。
Namespace(命名空间):
命名空间是对表的逻辑分组,类似于关系型数据库中的database。利用命名空间,在多租户场景下可以达到更好的资源和数据隔离效果。table(表):
Hyperbase以表维单位组织数据。表由多行组成。row(行):
表以行维单位组织数据。行由一个rowkey和多个列族组成。rowkey(行键):
是Hyperbase表中决定一行数据的唯一标识。rowkey是按照字典顺序进行排列。rowkey最多能存储64k字节的数据。column family(列族)&column(列)&Column qualifier(列限定符):
Hyperbase表中的每一个列都归属于某个列族,列族必须作为Schema定义的一部分预先给出;列族必须在建表时明确定义,入:create ‘student’,‘basicinfo’,‘courseinfo’列由列族和列限定符唯一指定,形式为列族:列限定符;每一个列族都可以有多个列,新的列可以在表创建后,动态的加入某个列族;权限控制、存储以及调优都是在列族层面进行的。物理上,同一列族的数据存储在一起 注:以行的形式体现表,但是是以列的形式存储数据的。cell(单元格):
由行和列的坐标交叉所决定;Hyperbase中的单元格中所存储的都是字节数组(Byte[]),也就是说Hyperbase单元格中的数据是没有类型的,全部都是字节码的形式进行存储。timestamp(时间戳):
在Hyperbase中每个cell存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异;不同版本的数据按照时间倒序排序,最新的数据排在最上面;时间戳可以在数据写入时由Hyperbase自动赋值,同样也可以由用户来手动赋值,但是如果要避免数据版本之间的冲突,就必须由用户自己生成具有唯一性的时间戳;时间戳的数据类型是64位整形。为了避免数据存在过多版本造成的的管理(包括存贮和索引)负担,Hyperbase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本。数据在Hyperbase中的数据读取流程为table->rowkey->column family->column->cell->ti mestamp。HMaster是Hbase集群的主节点,它对于自身而言管理元数据,并管理表的创建、删除和修改。作为集群管理者,它为HRegionServer分配Region,并保证HRegionServer的负载均衡(分配均匀数量的Region),但不处理Client的数据读写请求。
HRegionServer是Hbase集群的从节点,它负责处理Client的读写请求,管理Region的分裂和Storefile的合并。
Zookeeper除了负责HMaster的高可用之外,还负责监控HRegionServer的上下线信息,并通知HMaster。而且存储元数据的寻址入口和所有Region的寻址入口。(注:与hdfs的主从不同的是,在HRegionServer处理来自客户端的请求的时候,不会通过HMaster,而是由Zookeeper直接找到hmaster存储的元数据的hyperbase表,查找到目标表的HRegionServer,在哪些Region中存放,然后将元数据缓存在client节点之后再通过HRegionServer来对表数据操作)。
client通过接口访问hyperbase,为了加快数据访问速度,将元数据,region位置等信息缓存在client cache中。
Region是Hyperbase中分布式存储和负载的最小单元。系统会将表中数据按照rowkey划分为多个Region,每一个Region中保存表中的一段数据,默认情况下每一张表一开始只有一个Region,但是随着数据的写入,Region会不断的增大,当Region的大小超过阈值时,会分裂为两个Region,以此类推,并且随着Region的不断分裂,HMaster会将部分Region迁移到其他的HRegionServer中去来实现负载均衡,因此一张表中的数据通常被保存在多个HRegionServer的多个Region中。(注:很方便的通过rowkey进行切分)
Region是由多个Store组成的,每一个Store存储表中一个列族的数据。Store由内存中的MemStore以及磁盘中的StoreFile两部分构成。
MemStore是Store的内存缓冲区,数据读写都要首先经过MemStore。而StoreFile是MemStore的磁盘溢写文件,在HDFS中被称为HFile。在Hyperbase写入数据时,数据先被写入MemStore,当MemStore中的数据达到阈值时,HRegionServer会将MemStore中的数据溢写入磁盘中,每一次溢写都生成一个独立的StoreFile,StoreFile文件落在HDFS中被称为HFile。当StoreFile的数量超过阈值时,HRegionServer会将若干小的StoreFile合并成为一个大的StoreFile。(注:落小文件会在巡道时对hdfs造成压力)在Client从Hyperbase中读取数据时,Client会先找MemStore(注:因为在没有达到阀值时,MemStore中的数据不会写入到StoreFile,如果不先读MemStore则会少读到一部分数据),之后再去读取StoreFile。(当Region中Store大大小超过一定的阈值时,HRegionServer会将其等分成两个Region)
HLog是预写日志产生的日志文件,就是说Hyperbase在进行操作时,会首先将操作写入日志,后进行具体操作,即先写HLog,再写MemStore,最后由MemStore溢写出StoreFile。HLog的存在意义就是在HRegionServer意外宕机时作为数据恢复的依据。每一个HRegionServer都会维护一个自己的HLog,并且HLog会定期将过期数据进行清理。
Hyperbase的数据恢复过程:
1. 首先HMaster通过Zookeeper自动感知HRegionServer的宕机; 2. HMaster会处理HLog,并针对不同的Region将HLog进行拆分; 3. HMaster重新分配失效的Region; 4. 通过HLog将尚未持久化的数据重新写入MemStore,然后溢写到StoreFile。
当有一张表的数据在写入Hyperbase时,Region会在写入的过程中分裂为多个Region,这样的多个Region均匀的存储在HRegionServer中,而我们的客户端在进行读请求时也是直接访问的HRegionServer。
HRegionServer中的一个Region会根据表结构中的列族细分为多个Store,每一个Store存储一个列族的数据,而这些Store由有MemStore和StoreFile之分,数据在写入时,首先写入MemStore,当MemStore中的数据达到阈值时,HRegionServer会将这些MemStore中的数据溢写为StoreFile文件,StoreFile文件为HDFS当中持久化文件,即HFile文件。
随着MemStore中的数据不停的溢写为StoreFile文件,StoreFile文件的数据量过多超过阈值,这些StoreFile文件就会进行合并,合成为一个大的StoreFile文件。这些大的StoreFile文件最终存储到HDFS上就是HFile文件。
Hbase的表为什么是稀疏的结构呢?PPT中的图示可以说明,在一个列族进行存储的时候,会按行去进行扫描,有数据就会进行存储,没有数据就不进行存储。最终存储成key-value的形式保存成StoreFile。
StoreFile Compaction的含义是将Store中的全部或者部分StoreFile合并为一个StoreFile的过程,其目的是为了减少StoreFile文件的数量,提升数据读取的效率。
StoreFile Compaction的分类:
1. Minor Compaction就是在StoreFile合并时,选取Store下的部分的StoreFile进行合并,一般选取的标准是相邻或者比较小的StoreFile进行合并,将这些StoreFile合并为一个大的StoreFile。这种合并机制速度较快,并且IO和带宽的开销相对较低,除此之外,该合并机制对于版本过期的数据不会进行删除,只会删除被标记为删除的数据。
2. Major Compaction就是在StoreFile合并时,将Store下的所有StoreFile和并为一个StoreFile,该合并机制对于IO以及带宽的开销非常高,速度很慢,并且会对版本过期的数据进行删除,并删除标记为删除的数据。
当Region的大小达到阈值时,HRegionServer会将这个Region分裂为两个小的Region,这个过程就是Region Split,Region Split的目的是为了保证数据的负载均衡。
Region Split的具体方法是利用Middle Key将当前Region划分为两个等量的Region。当Region中最大的Store的大小超过阈值时,触发Region Split,并且Split会产生大量的IO操作,在Split开始前和完成后,HRegionServer都会通知HMaster,在Split完成后,HRegionServer会更新meta表。
写操作中,首先Client会去访问Zookeeper来获取meta表所在Region的位置信息,并将该信息写入Client Cache。之后Client读取meta表,后根据Namespace、表名和rowkey,来获取将要写入Region的位置信息,并将meta表写入Client Cache,之后就由Client与HRegionServer直接交互完成写操作。Client向HRegionServer发出写请求,HRegionServer先将操作和数据写入HLog,再将数据写入MemStore,并保持有序。当MemStore达到阈值时,将数据溢写入磁盘,生成StoreFile文件。当StoreFile文件数量超过阈值时,触发StoreFile Compaction将若干StoreFile进行合并。当Region中最大的StoreFile文件大小超过阈值时,Region分裂为两个Region。
读操作中,同样Client会去访问Zookeeper来获取meta表所在的Region的位置信息,并将该信息写入Client Cache。之后Client读取meta表,并根据Namespace、表名和rowkey来获取将要读取的Region的位置信息,将meta表写入Client Cache,后由Client和HRegionServer直接交互。Client向HRegionServer发出读请求。HRegionServer会先从MemStore中读取数据,如果未找到、再从StoreFile中读取数据。
一级索引就是指各行数据按照rowkey的字典顺序排列,通过rowkey来查询表中对应数据。一级索引对rowkey的查询效率很高,但是无法实现基于列的条件查询,在某些场景下不太适用。
通过在某个或者某些列上建立二级索引,达到创建全局索引的目的,实现基于列的快速条件查询。一张表可以创建多个全局索引。