详细讲解Hadoop中的一个简单数据库HBase
HBase是Hadoop中的一个简单数据库。它与Google的Bigtable特别相似,但也存在许多的不同之处。
数据模型
HBase数据库使用了和Bigtable非常相似的数据模型。用户在表格里存储许多数据行。每个数据行都包括一个可排序的关键字,和任意数目的列。表格是稀疏的,所以同一个表格里的行可能有非常不同的列,只要用户喜欢这样做。
?
列名是“<族名>:<标签>”形式,其中<族名>和<标签>可以是任意字符串。一个表格的<族名>集合(又叫“列族”集合)是固定的,除非你使用管理员权限来改变表格的列族。不过你可以在任何时候添加新的<标签>。HBase在磁盘上按照列族储存数据,所以一个列族里的所有项应该有相同的读/写方式。
?
写操作是行锁定的,你不能一次锁定多行。所有对行的写操作默认是原子的。
?
所有数据库更新操作都有时间戳。HBase对每个数据单元,只存储指定个数的最新版本。客户端可以查询“从某个时刻起的最新数据”,或者一次得到所有的数据版本。
?
概念模型
从概念上,一个表格是一些行的集合,每行包含一个行关键字(和一个可选的时间戳),和一些可能有数据的列(稀疏)。下面的例子很好的说明了问题:
?
?
?
?
物理模型
在概念上表格是一个稀疏的行/列矩阵,但是在物理上,它们按照列存储。这是我们的一个重要设计考虑。
?
上面“概念上的”表格在物理上的存储方式如下所示:
?
?
?
?
?
请大家注意,在上面的图中,没有存储空的单元格。所以查询时间戳为t8的“content:”将返回null,同样查询时间戳为t9,“anchor:”值为“my.look.ca”的项也返回null。
?
不过,如果没有指明时间戳,那么应该返回指定列的最新数据值,并且最新的值在表格里也时最先找到的,因为它们是按照时间排序的。所以,查询“contents:”而不指明时间戳,将返回t6时刻的数据;查询“anchor:”的“my.look.ca”而不指明时间戳,将返回t8时刻的数据。
?
例子
为了展示数据在磁盘上是怎么存储的,考虑下面的例子:
?
程序先写了行“[0-9]”,列“anchor:foo”;然后写了行“[0-9]”,列“anchor:bar”;最后又写了行“[0-9]”,列“anchor:foo”。当把memcache刷到磁盘并紧缩存储后,对应的文件可能如下形式:
?
hbaserepository, w-nk5YNZ8TBb2uWFIRJo7V==,6890601455914043877
元数据表
我们也可以使用这种标识符作为不同子表的行标签。于是,子表的元数据就存储在另一个子表里。我们称这个映射子表标识符到物理子表服务器位置的表格为元数据表。
?
元数据表可能增长,并且可以***成多个子表。为了定位元数据表的各个部分,我们把所有元数据子表的元数据保存在根子表(ROOT table)里。根子表总是一个子表。
?
在启动时,主服务器立即扫描根子表(因为只有一个根子表,所以它的名字是硬编码的)。这样可能需要等待根子表分配到某个子表服务器上。
?
一旦根子表可用了,主服务器扫描它得到所有的元数据子表位置,然后主服务器扫描元数据表。同样,主服务器可能要等待所有的元数据子表都被分配到子表服务器上。
?
最后,当主服务器扫描完了元数据子表,它就知道了所有子表的位置,然后把这些子表分配到子表服务器上去。
?
主服务器在内存里维护当前可用的子表服务器集合。没有必要在磁盘上保存这些信息,因为主服务器挂掉了,整个系统也就挂掉了。
?
Bigtable与此不同,它在Google的分布式锁服务器Chubby里储存“子表”到“子表服务器”的映射信息。但我们把这些信息存储到元数据表里,因为Hadoop里没有等价Chubby的东西。
?
这样,元数据和根子表的每行“info:”列族包含3个成员:
?
1.Info:regioninfo包含一个序列化的HRegionInfo对象。
?
2.Info:server包含一个序列化的HServerAddress.toString()输出字符串。这个字符串可以用于HServerAddress的构造函数。
?
3.Info:startcode是一个序列化的long整数,由子表服务器启动的时候生成。子表服务器把这个整数发送给主服务器,主服务器判断元数据和根子表里的信息是否过时了。
?
所以,客户端只要知道了根子表的位置,就不用连接主服务器了。主服务器的负载相对很小:它处理超时的子表服务器,启动时扫描根子表和元数据子表,和提供根子表的位置(还有各个子表服务器间的负载均衡)。
?
HBase的客户端则相当复杂,并且经常需要结合根子表和元数据子表来满足用户扫描某个表格的需求。如果某个子表服务器挂了,或者本来应该在它上面的子表不见了,客户端只能等待和重试。在启动的时候,或最近有子表服务器挂掉的时候,子表到子表服务器的映射信息很可能不正确。
?
结论:
1.子表服务器提供对子表的访问,一个子表只由一个子表服务器管理。
?
2.子表服务器需要向主服务器“报到”。
?
3.如果主服务器挂了,整个系统就挂了。
?
4.只有主服务器知道当前的子表服务器集合。
?
5.子表到子表服务器的映射存储在2种特殊的子表里,它们和其他子表一样被分配到子表服务器上。
?
6.根子表是特殊的,主服务器总是知道它的位置。
?
7.整合这些东西是客户端的任务