HBase是一个类似Bigtable的分布式数据库,它的大部分特性和Bigtable一样,是一个稀疏的、长期存储的(存在硬盘上〉、多维度的排序映射表.这张表的索引是行关键字、列关键字和时问戳。每个值是一个不解释的字符数组,数据都是字符扇,没有类型。用户在 表格中存储数据,每一行都有一个可排序的主键和任意多的列。由于是稀疏存储的,所以 同一张表里面的每一行数据都可以有截然不同的列。列名字的格式是“<family>:<label>”, 它是由字符串组成的,每一张表有一个family集合,这个集合是固定不变的,相当于表的结构,只能通过改变表结构来改变表的family集合,但是label值相对于每一行来说都是 可以改变的。

        HBase把同一个family中的数据存储在同一个目录下,而HBase的写操作是锁行的,每一行都是一个原子元素,都可以加锁,所有数据库更新都有一个时间戳标记,每次更新都会产生一个新的版本,而HBase会保留一定数量的版本,这个值可以设定,客户端可以选择获取最近的某个时间的版本或者所有的版本。

        以上从微观上介绍了HBase的一些数据管理措施。 那么HBase作为分布式数据库在整体上从集群出发又是如何管理数据的呢?
        HBase在分布式集群上主要依靠囱HRegion、 HMaster、 HClient组成的体系结构从整体上管理数据。

        HBase体系结构的三大重要组成部分是:
            1.HBaseMaster : HBase主服务器, 与Bigtable的主服务器类似。
            2.HRegionServer : HBase域服务器, 与Bigtable的Tablet服务器类似。
            3.HBaseClient : HBase客户端是由org.apache.hadoop.HBase.client.HTable定义的。
下面将对这三个组件进行详细的介绍。
(1) HBaseMaster 
        一个HBase只部署一台主服务器, 它通过领导选举算撞( Leader Election Algorithm)确保只有唯一的主服务器是活跃的, ZooKeeper保存主服务器的服务器地址信息。 如果主服务器瘫痪, 可以通过领导选举算法从备用服务器中选择新的主服务器。
        主服务器初始化集群。当主服务器第一次启动时, 会试图从HDFS获取根或根域目录,若在取失败则创建根或根域目录, 以及第一个元域目录。 下次启动肘, 主服务器就可以获取集群和集群中所有域的信息了。
        主服务器负责域的分配工作。 首先, 主服务器会分配根域, 并存储指向根域所在域服务器地址的指针。 其次, 主服务器遍历根域查询元域, 并分配元域到域服务器中。 每个元域中包含了所有的用户域, 用户域中存储了多个用户表。 如果所有的元域分配完毕, 主服务器将 会分配用户域到相应的域服务器, 以保持域服务器间的负载平衡。
        主服务器时刻监视着域服务器的运行状态。 一且主服务器检测到某一域服务器不可达时, 它将分离出域服务器上的每个域的预写日志C write-ahead log)文件。 之后, 主服务器 会将域重新分配到其他域服务器上, 并运行之。 如果主服务器发现一个域服务器超负荷运行, 则会取消Il1t关闭该域服务器的一些域, 并将这些域分配到其他低负载的域服务器上。

        主服务器还负责表格的管理。 例如, 调整表格的在线/离线状态和改变表格的模式(增加或删除列族)等。 此外, 客户端还可以请求本地域直接从域服务器上读取数据。
        在Bigtable中, 当主服务器和城服务器的连接断开时, 域服务器仍然可以继续服务, 因为Bigtable提供了一种额外的锁管理机制, 这种机制中的锁管理器(Chubby)保证了域服务器服务的可用性。 而在 HBase中, 由于没有提供锁管理机制, 当主服务器崩溃时, 整个集群系统都要重新启动, 因为主服务器是所有域服务器的管理中心。

         下面介绍元表和根表的概念:
        元袤(Meta Table)包含了所有用户域的基本信息, 域信息包括起始关键字、 结束关键字、 域是否在线、 域所在的域服务器地址等。 元表会随着用户域的增长而增长。

        根表(Root Table)被定义为存储单一域的信息,并指向元表中的所有域。与元表一样, 根表也包含每个元域的信息和元域所在的域服务器地址.
        根表和元表中的每行大约为1KB。域默认大小为256MB,根城可以映射2.6×10的5次方个元域。同样,元域可以映射相应数量的用户域.因此,根域可以映射6.9×10的10次方个用户域,大约可以存储1.9×10的19次方节的数据。

        ( 2) HRegionServer
        HBase域服务器主要有服务于主服务器分配的域、处理客户端的读写请求、缓冲区回写、压缩和分割域等功能.
        每个域只能由一台域服务器来服务.当它开始服务于某域时,它会从HDFS文件系统中读取该域的日志和所有存储文件.同时它还会管理操作HDFS文件的持久性存储工作。
        客户端通过与主服务器通信获取域和域所在域服务器的列表信息后,就可以直接向域服务器发送域读写请求了.域服务器收到写请求时,首先将写请求信息写入一个预写日志文件中,该文件取名为HLog.同一个域的所有写请求都被记录在同一个HLog文件中。一且写请求被记录在HLog中之后,它将被缓存在存储缓存区(MemCache)中.每个HStore对应 一个存储缓存区.对于读请求,域服务器先要检测请求数据在存储缓存区中是否被命中,如果没有命中,域服务器再去查找相关的映射文件。
        当存储缓存区的大小达到一定阈值后,需要将存储缓存区中的数据因写到磁盘上,形成映射文件,并在HLog日志文件中标记。因此当再次执行时,可以跳跃到最后一次回写之前的操作上.回写也可能因域服务器存储器压力而被触发.
        当映射文件的数量达到一定阈值肘,域服务器会将最近常写入的映射文件进行轻度的合并压缩.此外,域服务器还会周期性地对所有的映射文件进行压缩,使其成为单一的映射文件.之所以周期性地压缩所有的映射文件,是因为最早的映射文件通常都比较大,而最近的映射文件则要小很多,压缩要消耗很多的时间,具体消耗的时间主要取决于读取、合并和写出最大映射文件所需要的IO操作次数.压缩和处理读写请求是同时进行的。在一个新的映射文件移入之前,读写操作将被挂起,直到映射文件被加入HStore的活跃映射文件列表中, 且已合并的旧映射文件被删除后,才会释放读写操作.
        当HStore中映射文件的大小达到一定的阈值时〈目前默认的阈值为256MB),域服务器就要对域进行分割了.域被均分为两个子域,分割操作执行速度很快,因为子域是直接从父域中读取数据的。之后,父域处于离线状态。域服务器在元域中记录新的子域,并通知主服务器可以将子域分配给其他域服务器。如果域分割消息在网络传输中丢失,主服务器可以在周期性扫描元域中未被分配的模信息时发现分割操作。一且父域被关闭,所有对父域的读写操作将被挂起.客户端则会探测域的分割信息,当新的子域在线时,客户端再发出读写请求。当子域触发压缩操作时,父域的数据将复制到子域中.父域将会在两个子域都完成压缩操作时被回收。

        ( 3 ) HBaseClient 
        HBase客户端负责查找用户域所在的域服务器地址.HBase客户端会与HBase主机交换消息以查找根域的位置, 这是两者之间唯一的交流。
        定位根域后 , 客户端连接根域所在的域服务器, 并扫描根域获取元域信息,元域包含所需用户域的域服务器地址。 客户端再连接元域所在的域服务器 ,扫描元域来获取所需用户城所在的域服务器地址。 定位用户域后, 客户端连接用户域所在的域服务器并发出读写请求。 用户端的地址将在容户端中被缓存, 后续的请求无须重复上述过程。
        不管是由于主服务器为了负载均衡而重新分配域还是域服务器崩槽, 客户端都会重新扫描元表来定位新的用户域地址。 如果元域被重新分配 , 客户端将扫描根域来定位新的元域地址。 如果根域也被重新分配, 客户端将会连接主机定位新的根域地址,并通过重复上述过程 来定位用户域地址。
        综上所述, 在HBase的体系结构中, HBase主要由主服务器、 域服务器和客户端三部分组成。 主服务器作为HBase的中心, 管理着整个集群中的所有域, 监控每个域服务器的运行情况等;域服务器接收来自服务器的分配域, 处理客户端的域读写请求并回写映射文件等; 客户端主要用来查找用户域所在的域服务器地址信息。