ROOT表和META表
先看一下HBase的相关的机制是怎样的。之前我们说过HRegion是按照表名和主键范围来区分的,由于主键范围是连续的,所以一般用开始主键就可以表示相应的HRegion了。
不过,因为我们有合并和分割操作,如果正好在执行这些操作的过程中出现死机,那么就可能存在相同的“表名和开始主键”,这样的话只要开始主键就不够了,着就要通过HBase的元数据信息来区分哪一份才是正确的数据文件,为了区分这样的情况,每个HRegion都有一个‘regionId’来标识它的唯一性。
所以一个HRegion的表达符最后是:表名+开始主键+唯一ID(tablenem+startkey+regionId)。我们可以用这个识别符来区分不同的HRegion,这些数据就是元数据(META),而元数据本身也是被保存在HRegion里面的,所以我们称这个表为元数据表(META Table),里面保存的就是HRegion标识符和实际HRegion服务器的映射关系。
元数据表也会增长,并且可能被分割为几个HRegion,为了定位这些HRegion,我们采用了一个根数据表(ROOT table),它保存了所有元数据表的位置,而根数据表是不能被分割的,永远只存在一个HRegion。
在HBase启动的时候,主服务器先去扫描根数据表,因为这个表只会有一个HRegion,所以这个HRegion的名字是被写死的。当然要把根数据表分配到一个HRegion服务器中需要一定时间。
待根数据表被分配好之后,主服务器就会去扫描根数据表,获取元数据表的名字和位置,然后把元数据表分配到不同的HRegion服务器中。最后就是扫描元数据表,找到所有HRegion区域的信息,然后把它们分配给不同的HRegion服务器。
主服务器在内存中保存着当前活跃的HRegion服务器的数据,因此如果主服务器死机,整个系统也就无法访问了,这时服务器的信息也就没有必要保存到文件里面了。
元数据表和根数据表的每一行都包含一个列族(info列族):
info:regioninfo:包含了一个串行化的HRegionInfo对象
info:server:保存了一个字符串,是服务器的地址HServerAddress.toString()。
info:startcode:是一个长整型数字的字符串,它是在HRegion服务器启动的时候传给主服务器的,让主服务器确定这个HRegion服务器的信息有没有更改。
因此,一个客户端在拿到根数据表地址后,就没有必要再链接主服务器了。主服务器的负载相对就小了很多,它只会处理超时的HRegion服务器,并在启动的时候扫描根数据表和元数据表,以及返回根数据表的HRegion服务器地址。
ROOT表包含META表所在的区域列表,META表包含所有的用户空间区域列表,以及Region服务器地址。客户端能够缓存所有已知的ROOT表和META表,从而提高访问的效率。
HBase数据模型
HBase是一个类似Bigtable的分布式数据库,它是一个稀疏的长期存储的(存在硬盘上)多维度的、排序的映射表。这张表的索引是行关键字、列关键字和时间戳。HBase中数据都是字符串,没有类型。
用户在表格中存储数据,每一行都有一个可排序的主键和任意多的列。由于是稀疏存储,所以同一张表里面的每一行数据都可以有截然不同的列。
列名字的格式是“<family>:<qualifier>”,都是由字符串组成的。每一张表有一个列族(family)集合,这个集合是固定不变的,只能通过改变表结构来改变。但是qualifier的值相对于每一行来说都是可以改变的。
HBase把同一个列族里面的数据存储在同一个目录底下,并且HBase的写操作是锁行的,每一行都是一个原子元素,都可以加锁。
HBase所有数据库的更新都有一个时间戳标记,每个更新都是一个新的版本,HBase会保留一定数量的版本,这个值是可以设定的。客户端可以选择获取距离某个时间点最近的版本单元的值,或者一次获取所有版本单元的值。
概念视图
我们可以将一个表想象成一个大的映射关系,通过行键、行键+时间戳或行键+列(列族:列修饰符),就可以定位特定数据。由于HBase是稀疏存储的数据的,所以某些列可以空白的,
物理视图
虽然从概念视图来看每个表格是由很多行组成的,但是在物理存储上面,它是按照列来保存的,这点在进行数据设计和程序开发的时候必须牢记。
需要注意的是,在概念视图上面有些列是空白的,这样的列实际上并不会被存储,当请求这些空白的单元格时,会返回null值。
如果在查询的时候不提供时间戳,那么会返回距离现在最近的那一个版本的数据,因为在存储的时候,数据会按照时间戳来排序。
HBase与RDBMS
HBase就是一个基于列模式的映射数据库,它只能表示和简单的键-数据的映射关系,这大大简化了传统的关系数据库。与关系数据库相比,它有如下特点:
数据类型:HBase只有简单的字符串类型,所有的类型都是交由用户自己处理的,它只保存字符串。而关系型数据库有丰富的类型选择和存储方式。
数据操作:HBase操作只有很简单的插入、查询、删除、清空等操作,表和表之间是分离的,没有复杂的表和表之间的关系,所以不能也没有必要实现表和表之间的关联等。传统的关系数据库是基于表格结构和行模式保护的。
数据维护:确切说,HBase的更新操作应该不叫更新,虽然一个主键或列会对应新的版本,但它的旧版本仍然会保留,所以它实际上是插入了新数据,而不是传统关系数据库里面的替换修改。
可伸缩性:HBase这类分布式数据库就是为了这个目的而开发出来的,所以它能够轻易地增加或减少(在硬件错误的时候)硬件数量,并且对错误的兼容性比较高。而传统的关系型数据库通常需要增加中间层才能实现类似的功能。