大数据学习之HBase

分布式数据库HBase

HBase简介

HBase是一种高可靠、高性能、面向列、课伸缩的分布式数据库,是谷歌BigTable的开源实现,主要用来存储非结构化和半结构化的松散数据。HBase的目标是处理非常庞大的表,能够通过水平扩展的方式,利用廉价计算机集群处理超过大规模的数据表。
在Hadoop生态体系中,HBase利用Hadoop MapReduce来处理HBase中的海量数据,实现高性能计算;利用Zookeeper作为协同服务,实现稳定服务和失败恢复;使用HDFS作为高可靠的底层存储,利用廉价集群提供海量数据存储能力。当然,HBase也可以直接使用本地文件系统而不用HDFS作为底层数据存储方式,不过为了提高数据可靠性和系统的健壮性,发挥HBase处理大数据量的功能,通常都使用HDFS作为HBase的底层数据存储方式。此外,为了方便在HBase上进行数据处理,Sqoop为HBase提供了高效、便捷的RDBMS数据导入功能,Pig和Hive为HBase提供了高层语言支持。

HBase和传统数据关系数据库的对比分析
1.数据类型:
关系型数据库采用关系模型,具有丰富的数据类型和存储方式,HBase则采用了更加简单的数据模型。它把数据存储为未经解释的字符串,用户可以把不同格式的结构化数据和非结构化数据都序列化成字符串,保存到HBase中,用户需要自己编写程序把字符串解析成不同的数据类型。
2.数据操作:
关系数据库中包含了丰富的操作,比如插入、删除、更新等等,其中会涉及到复杂的多表连接,通常是借助于多个表之间的主外键关联来实现的。HBase操作则不存在复杂的表和表之间的关系,只有简答的插入、查询、删除等。因为HBase在设计上就避免了复杂的表和表之间的关系,通常只采用单表的主键查询,所以无法实现像关系数据库中那样的表和表之间的连接操作。
3.存储模式:
关系数据库是基于行模式存储的,元组或行会被连续的存储在磁盘页中。在读取数据时,需要顺序扫描每个元组,然后从中筛选出查询所需要的的属性。如果每个元组中只有少量属性的值对于查询是有用的,那么急于行模式存储就会浪费许多磁盘控件和内存带宽。HBase是基于列存储的,每个列族都由几个文件保存,不同列族的文件是分离的,这样做的优点是:可以降低I/O开销,支持大量并发用户查询,因为仅需要处理能够回答查询的列就可以,而不需要处理与查询无关的大量数据行;而且同一个列族中的数据会一起进行压缩,由于同一列族内的数据相似度较高,因此可以获得较高的数据压缩比。
4.数据索引:
关系数据库通常可以针对不同列构建复杂的多个索引,以提高数据访问性能。而HBase只有一个索引——行键,通过巧妙的设计,HBase中的所有访问方法,通过行键进行访问或者扫描,使得整个系统不会慢下来。由于HBase位于Hadoop框架上,因此可以使用hadoop MapReduce来快读、高效的生成索引表。
5.数据维护
在关系数据库中,更新操作会用更新后的值去替换原来的值,旧的值被替换后就不存在了。但是在HBase中执行更新操作时,并不会删除数据的旧版本,而是生成一个新的本本,旧的版本仍然保留。
6.可伸缩性
关系数据库很难实现横向扩展,纵向扩展的空间也比较有限。相反,HBase就是为了实现灵活的水平扩展而开发的,能够轻易的通过在集群中增加或者减少硬件数量来实现性能的伸缩。

但是,相对于关系数据库来说,HBase也有自身的局限性,比如HBase不支持事务,因此,无法实现跨行的原子性。

HBase数据模型

1.数据模型概述:
HBase是一个稀疏、多维度、排序的映射表,这张表的索引是行键、列族、列限定符和时间戳。每个值是一个未经解释的字符串,没有数据类型。用户在表中存储数据,每一行都有一个可排序的行键和任意多的列。表在水平方向由一个或者多个列族组成,一个列族中可以包含任意多个列,同一列族里面的数据是存储在一起的。列族支持动态扩展,可以很轻松的添加一个列族或列,无需预先定义列的数量以及类型,所有列均以字符串的形式存储,用户需要自行进行数据类型转换。由于同一张表里面的每一行数据都可以有截然不同的列,因此,对于整个映射表的每行数据而言,有些列的值就是空的,所以说HBase是稀疏的。
在HBase中执行更新操作时,并不会删除数据旧的版本,而是生成一个新的版本,旧有的版本仍然保留,HBase可以对允许保留的版本的数量进行设置。客户端可以选择获取距离某个时间最近的版本,或者一次获取所有的版本。如果在查询的时候不提供时间戳,那么会返回距离现在最近的那一个版本的数据,因为在存储的时候,数据会按照时间戳排序。HBase提供了两种数据版本回收方式:一是保存数据的最后n个版本,而是保存最近一段时间内的版本。

2.数据模型的相关概念:
HBase实际上就是一个稀疏、多维、持久化存储的映射表,它采用行键(Row Key)、列族(Column Family)、列限定符(Column Qualifier)和时间戳(Timestamp)进行索引,每个值都是未经解释的字节数组byte[]。下面具体介绍HBase数据模型的相关概念。
1)表
HBase采用表来组织数据,表有行和列组成,列划分为若干个列族。
2)行
每个HBase表都有若干行组成,每个行由行键(Row Key)来标识。访问表中的行只有3种方式:通过单个行键访问;通过一个行键的区间来访问;全表扫描。行键可以是任意字符串(最大长度是64Kb)。在HBase内部,行键保存为字节数组,存储时,数据按照行键的字典序排序存储。
3)列族
一个HBase表被分组成许多“列族”集合,它是基本的访问控制单元。列族需要在表创建时就定义好,数量不能太多,而且不要频繁修改。存储在一个列族当中的所有数据,通常都属于同一数据类型,这通常意味着更高的压缩率。表中的每个列都归属于某个列族,数据可以被存放到列族的某个列下面,但是,在把数据存放到这个列族的某个列下面之前,必须首先创建这个列族。列名都以列族作为前缀的。在HBase中,访问控制、磁盘和内存的使用统计都是在列族层面进行的。
4)列限定符
列族中的数据通过列限定符(列)来定位。列限定符不用事先定义,也不需要在不同行之间保持一致。列限定符没有数据类型,总被视为字节数组byte[]。
5)单元格
在HBase中,通过行、列族和列限定符确定一个“单元格”(cell)。单元格中存储的数据没有数据类型,总被视为字节数组byte[]。每个单元格中可以保存一个数据的多个版本,每个版本对应一个不同的时间戳。
6)时间戳
每个单元格都保存着同一份数据的多个版本,这些版本采用时间戳进行索引。每次对一个单元格执行操作(新建、修改、删除)时,HBase都会隐式的生成并存储成一个时间戳。时间戳一般是64位整形,可以由用户自己赋值(自己生成唯一时间戳可以避免应用程序中出现数据版本冲突),也可以由HBase在数据写入时自动复赋值。一个单元格的不同版本是根据时间戳降序的顺序进行存储的,这样,最新的版本可以被最先读取。
在这里插入图片描述
上图为HBase数据模型的一个实例

3.数据坐标
HBase使用坐标来定位表中的数据,也就是说,每个值都是通过坐标来访问的。在HBase中需要根据行键。列族。列限定符和时间戳来确定一个单元格,因此可以视为一个“四维坐标”,即【行键,列族,列限定符,时间戳】。

4.面向列的存储
通过前面的论述,我们已经知道HBase是面向列的存储,也就是说,HBase是一个“列式数据库”。而传统的关系数据库采用的是面向行的存储,被称为“行式数据库”。
行式数据库使用NSM(N-ary Storage Model)存储模型,一个元组(行)会被连续的存储在磁盘页中。也就是说,数据是一行一行被存储的,第一行写入磁盘页后,再继续写入第二行,以此类推。从磁盘中读取数据的时候,需要从磁盘中顺序扫描每个元组的完成内容,然后,从每个元组中筛选出查询所需要的属性。如果每个元组只有少量属性的值对于查询是有用的,那么NSM就会浪费许多磁盘空间和内存带宽。

列式数据库采用DSM(Decomposition Storge Model)存储模型,它是在1985年提出来的,目的是为了最小化无用的I/O。DSM采用了不同于NSM的思路,对于采用DSM存储模型的关系数据库而言,DSM会对关系进行垂直分解,并为每个属性分配一个子关系,因此一个具有n个属性的关系,会被分解成n个子关系,每个子关系单独存储,每个子关系只有当其相应的属性被请求时才会被访问。也就是说,DSM是以关系数据库中的属性或列为单位进行存储,关系中多个元组的同一属性值(或同一列值)会被存储在一起,而一个元组中不同属性值则通常会被分别放于不同的磁盘页中。

行式数据库主要适合于小批量的数据处理,如联机事务性数据处理。比如Oracle和MySQL。列式数据库主要适合于批量数据处理和即时查询,它的优点是:可以降低I/O开销,支持大量并发用户查询,数据处理速度比传统方法要快很多,因为仅需要处理可以回答这些查询的列,而不是分类整理与也定查询无关的数据行;具有较高的数据压缩比,较传统的行式数据库更加有效。列式数据库主要用于数据挖掘、决策支持和地理信息系统等查询密集型系统中,因为一次查询就可以得出结果,而不必每次都要遍历所有的数据库。

列式数据库的缺陷是,执行连接操作时需要昂贵的元组重构代价。因为一个元组的不同属性被分散到不同磁盘页中存储,当需要一个完整的元组时,就要从多个磁盘页中读取相应字段的值来重新组合得到原来的一个元组。但是对于分析性应用而言,一般数据被存储后不会发生改变(如数据仓库),因此不会涉及到昂贵的元组重组代价。

HBase的实现原理

1.HBase的功能组件
HBase的实现包括3个主要的功能组件:
1)库函数,链接到每个客户端;
2)一个Master主服务器;
3)许多个Region服务器;
Region服务器负责存储和维护分配给自己的Region,处理来自客户端的读写请求。主服务器Master负责管理和维护HBase表的分区信息。比如,一个表被分成了哪些Region,每个Region被存在哪台Region服务器上,同时也负责维护Region服务器列表,因此如果Master主服务器死机,那么整个系统都会无效。Master会实时监测集群中的Region服务器,把特定的Region分配到可用的Region服务器上,并确保整个集群内部不同Region服务器之间的负载均衡。当某个Region服务器因出现故障而失效的时候,Master会把该故障服务器上存储的Region重新分配给其他可用的Region服务器。除此之外,Master还处理模式变化,如表和列族的创建。

但是客户端并不是直接从Master主服务器上服务数据,而是在获得Region的存储位置信息后,直接从Region服务器上服务数据。尤其需要指出的是,HBase客户端并不依赖Master,而是借助于Zookeeper来获得Region的位置信息。所有,大多数客户端从来不和主服务器Master通信,这种设计方式是Master的负载很小。
2.表和Region
在一个HBase中,存储了许多表。对于每个HBase表而言,表中的行是根据行键的值得字典序进行维护的。表中包含的行的数量可能非常庞大,无法存储在一台机器上,需要分布存储到多台机器上。因此,需要根据行键的值对表中的行进行分区,如下图所示:
在这里插入图片描述
如图进行分区以后,每个行区间构成一个分区,被称为“Region”,包含了位于某个值域区间内的所有数据。它是负载均衡和数据分发的基本单位,这些Region会被分发到不同的Region服务器上。

初始时,每个表只包含一个Region,随着数据的不断插入,Region会持续增大。当一个Region中包含的行数量达到一个阈值时,就会被自动等分成两个新的Region。随着表中行的数量持续增加,就会分裂成多个Region。如下图所示:
在这里插入图片描述
每个Region的默认大小是100M到200M,它是HBase中负载均衡和数据分发的基本单位。Master主服务器会把不同的Region分配到不同的Region服务器上(如下图)。但是,同一个Region是不会被拆分到多个Region服务器上的。每个Region服务器负责管理一个Region集合,通常在每个Region服务器上,会放置10~1000个Region。
在这里插入图片描述
3.Region的定位
一个HBase的表可能会非常庞大,会被分裂成很多个Region,这些Region被分发到不同的Region服务器上。因此,必须设计相应的Region定位机制,保证客户端知道到哪里可以找到自己所需要的数据。
每个Region都有一个RegionID来标识它的唯一性,这样一个Region标识符就可以标识成“表名+开始主键+RegionID”。
有了Region标识符,就可以唯一标识每个Region。为了定位每个Region所在的位置,就可以构建一张映射表,映射表的每个条目(或每行)包含两项内容,一个是Region标识符,另一个是Region服务器标识,这个条目就表示Region和Region服务器之间的对应关系,从而就可以知道某个Region被保存在哪个Region服务器中。这个映射表包含了关于Region的元数据(即Region和Region服务器之间的对应关系),因此,也被称为“元数据表”。又被称为“.META.表”。
当一个HBase表中的Region数量非常庞大的饿时候,.META.表的数目条目就会非常多,一个服务器保存不下,也需要分区存储到不同的服务器上。因此,.MATE.表也会被分裂成多个Region,这时为了定位这些Region,就需要再构建一个新的映射表,记录所有元数据的具体位置,这个新的映射表就是”根数据表“,又名”-ROOT-表“。-ROOT-表是不能被分割的,永远只存在一个Region用于存放-ROOT-表,因此,这个用来存放-ROOT-表的唯一一个Region,它的名字是在程序中被写死的,Master主服务器永远知道它的位置。
综上所述,HBase使用类似B+数的三层结构来保存Region位置信息,如图所示:
在这里插入图片描述
HBase三层结构中每个层次的名称及其具体作用如下表所示:
在这里插入图片描述
为了加快访问速度,.META.表的全部Region都会被保存在内存中。客户端在访问用户数据之前,需要首先访问Zookeeper,获取-ROOT-表的位置信息,然后访问-ROOT-表的,获得.META.表的信息,接着访问.META.表,找到所需的Region具体位于哪个Region服务器,最后才会到该Region服务器读取数据。该过程需要多次网络操作,为了加速寻址过程,一般会在客户端做缓存,那查询过的位置信息缓存起来,这样以后访问相同的数据时,就可以直接客户端缓存中获取Region的位置信息,而不需要每次都经历一个“三级寻址”过程。需要注意的是,随之HBase中表的不断更新,Region的位置信息可能会发生变化。但是,客户端缓存并不会自己检测Region位置信息是否失效,而是在需要访问数据时,从缓存中获取Region位置信息但是发现找不到的时候,才会判断缓存失效。这时,就需要再次经历上述的“三级寻址”过程,重新获取最新的Region位置信息去访问数据,并用最新Region位置信息替换缓存中失效的信息。
当一个客户端从Zookeeper服务器上拿到-ROOT-表的解析地址以后,就可以通过三级寻址找到用户数据表所在的Region服务器,并直接访问该Region服务器获得数据,没有必要再连接主服务器Master。因此,主服务器的负载相对就小了很多。

HBase运行机制

1.HBase系统架构
如下图所示,HBase的系统架构包括客户端、Zookeeper服务器、Master主服务器、Region服务器。HBase一般采用HDFS作为底层数据存储。
在这里插入图片描述
1)客户端
客户端包含访问HBase的借口,同时在缓存中维护这已经访问过的Region位置信息,用来加快后续数据访问过程。HBase客户端使用HBase的RPC机制与Master和Region服务器进行通信。其中,对于管理类操作,客户端与Master进行RPC,而对于数据读写类操作,客户端则会与Region服务器进行RPC。
2)Zookeeper服务器
Zookeeper服务器并非一台单一的机器,可能是由多台机器构成的集群来提供稳定可靠的协同服务。Zookeeper能够很容易的实现集群管理的功能,如果有多台服务器组成一个服务器集群,那么必须要一个“总管”知道当前集群中每台机器的服务状态,一旦某台机器不能提供服务,集群中其他机器必须知道,从而做出调整重新分配服务器策略。同样,当增加集群的服务能力时,就会增加一台或多台服务器,同样也必须让“总管”知道。

在HBase服务器集群中,包含了一个Master和多个Region服务器,Master就是这个HBase集群的“总管”,它必须知道Region服务器的状态。Zookeeper就可以轻松做到这一点,每个Region服务器都需要到Zookeeper中进行注册,Zookeeper会实时监控每个Region服务器的状态并通知给Master,这样Master就可以通过Zookeeper随时感知到各个Region服务器的工作状态。

Zookeeeper不仅能够帮助维护当前集群中机器的服务状态,而且能够bang住选出一个“总管”,让这个总管来管理集群。HBase中可以启动多个Master,但是,Zookeeper可以帮助选出一个Master作为集群的总管,并保证在任何时刻总有唯一一个Master在运行,这就避免了Master的“单点失效”问题。

Zookeeper中保存了-ROOT-表的地址和Master的地址,客户端可以通过访问Zookeeper获得-ROOT-表的地址,并最终通过三级寻址找到所需的数据。Zookeeper中还存储了HBase的模式,包括有哪些表,每个表有哪些列族。
3)Master
主服务器Master主要负责表和Region的管理工作:

a.管理用户对表的增加、删除、修改、查询等操作;
b.实现不同Region服务器之间的负载均衡;
c.在Region分裂或合并后,负责重新调整Region的分布;
d.对发生故障失效的Region服务器上的Region进行迁移。

客户端访问HBase上数据的过程并不需要Master参与,客户端访问Zookeeper获取-ROOT-表的地址,并最终到达相应的Region服务器进行数据读写,Master仅仅维护着表和Region的元数据,因此负载很低。

任何时刻,一个Region只能分配给一个Region服务器。Mater维护了当前可用的Region服务器列表,以及当前哪些Region分配给了哪些Region服务器,哪些Region还未被分配。当存在未被分配的Region,并且有一个Region服务器上有可用空间时,Master就给这个Region服务器发送一个请求,把该Region分配给它。Region服务器接收请求并完成数据加载后,就开始负责管理该Region对象,并对外提供服务。
4)Region服务器
Region服务器是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。HBase一般采用HDFS作为底层存储文件系统。因此,Region服务器需要向HDFS文件系统中读写数据。采用HDFS作为底层存储,可以为HBase提供可靠稳定的数据存储。HBase自身并不具备数据复制和维护数据副本的功能,而HDFS可以为HBase提供这些支持。当然,HBase也可以不采用HDFS,而是使用其他任何支持Hadoop接口的文件系统作为底层存储。

2.Region服务器工作原理
在这里插入图片描述

Region服务器是HBase中最核心的模块。上图中描述了Region服务器向HDFS文件系统中读写数据的基本原理。从图中可以看出,Region服务器内部管理了一些列Region对象和一个HLog文件。其中,HLog是磁盘上的记录文件,它记录着所有的更新操作。每个Region对象又是由多个Store组成的,每个Store对应了表中的一个列族的存储。每个Store又包含了一个MenStore和若干个StoreFile。其中,MemStore是在内存中的缓存,保存最近更新的数据,StoreFile是磁盘中的文件,这些文件都是B树结构的,方便快读读取。StoreFile在底层的实现方式是HDFS文件系统的HFile,HFile的数据块通常是采用压缩方式存储,压缩之后可以大大减少网络I/O和磁盘I/O。
1)用户读写数据的过程
当用户写入数据时,会被分配到相应的Region服务器去执行操作。用户数据首先被写入到MemStore和HLog中,当操作写入HLog之后,commit()调用才会将其返回给客户端。

当用户读取数据时,Region服务器会首先访问MenStore缓存,如果数据不在缓存中,才会到磁盘上面的StoreFile中去寻找。
2)缓存的刷新
MemStore缓存的容量有限,系统会周期性的调用Region.fiushcache()把MemStore缓存里面的内容写入到磁盘的StoreFile文件中,同时清空缓存,并在HLog文件中写入一个标记,用来表示缓存中的内容已经被写入StoreFile文件中。每次缓存刷新操作,都会在磁盘上生成一个新的StoreFile文件,因此每个Store会包含多个StoreFile文件。

每个Region服务器都有一个自己的HLog文件。在启动的时候,每个Region服务器都会检查自己的HLog文件,确认最近一个执行缓存刷新操作之后是否发生新的写入操作。如果没有更新,说明所有数据已经被永久保存到磁盘的StoreFile文件中;如果发现更新,就先把这些更新写入MemStore,然后再刷新缓存,写入到磁盘的StoreFile文件洪。最后,删除旧的HLog文件,并开始为用户提供数据访问服务。
3)StoreFile的合并
每个MemStore缓存的刷新操作,都会在磁盘上生成一个新的StoreFile文件,这样系统中的每个Store就会存在多个StoreFile文件。当需要访问某个Store中的值时,就必须查找所有这些StoreFile,非常耗费时间。因此,为了减少查找时间,系统一般会调用Store.compact()把多个StoreFile合并成一个大文件。由于合并操作比较耗费资源,因此只会在StoreFile文件的数量达到一个阈值的时候才会触发合并操作。

3.Store的工作原理
Region服务器是HBase的核心模块,而Store则是Region服务器的核心。每个Store对应了表中的一个列族的存储。每个Store包含一个MemStore缓存和若干个StoreFile文件。
MemStore是排序的内存缓冲区,当用户写入数据时,系统首先把数据放入MemStore缓存,当MemStore缓存满时,就会刷新到磁盘中的一个StoreFile文件中。随着StoreFile文件数量的不断增加,当达到事先设定的数量时,就会触发文件合并操作,多个StoreFile文件会被合并成一个大的StoreFile文件。当多个StoreFile合并后,就会逐步形成越来越大的StoreFile文件,当单个StoreFile文件大小超过一定阈值时,就会触发文件分裂操作。同时,当前的一个父Region会被分裂成2个字Region,父Region会下线,新分裂出的2个子Region会被Master分配到相应的Region服务器上。下图描述了StoreFile合并和分裂的过程:
在这里插入图片描述

4.HLog的工作原理
在分布式的环境下,必须要考虑到系统出错的情形。比如,当Region服务器发生故障时,MemStore缓存中的数据(还没有被写入文件)会全部丢失。因此,HBase采用HLog来保证系统发生故障时能够恢复到正确的状态。

HBase系统为每个Region服务器配置了一个HLog文件。它是一种预写shift日志(Write Ahead Log),也就是说用户更新数据必须首先被记入日子后才能写入MemStore缓存,并且直到MemStore缓存内容对应的日志已经被写入磁盘之后,该缓存内容才会被刷新写入磁盘。

Zookeeper会实时监测每个Region服务器的状态。当某个Region服务器发生故障时,Zookeeper会通知Master。Master首先会处理该故障Region服务器上面遗留的HLog文件,由于一个Region服务器上面可能会维护这多个Region对象,这些Region对象共用一个HLog文件,因此这个遗留的HLog文件中包含了来自多个Region对象的日志记录。系统会根据每条日志记录所属的Region对象读HLog数据进行拆分,分别放到相应Region对象的目录下,然后再将失效的Region重新分配到可用的Region服务器中,并把与该Region对象相关的HLog日志记录也发送给相应的Region服务器。Region服务器领取到分配给自己的Region对象以及与之相关的HLog日志记录以后,会重新做一遍日志记录中的各种操作,把日志记录中的数据写入MemStore缓存,然后刷新到磁盘的StoreFile文件中,完成数据恢复。

需要特别指出的是,HBase系统中每个Region服务器只需要维护一个HLog文件,所有Region对象共用一个HLog,而不是每i个Region使用一个HLog。在这种Region对象共用一个HLog的方式中,多个Region对象的更新操作所发生的日志修改,只需要不断的把日志记录追加到单个日志文件中,而不需要同时打开、写入多个日志文件中。因此可以减少磁盘磁盘寻址次数,提高对表的写操作性能。这种方式的缺点就是如果一个Region服务器发生故障,为了恢复其上的Region对象,需要将Region服务器上的HLog按照其所属的Region对象进行拆分,然后分发到其他Region服务器上执行恢复操作。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部