Hbase学习之概念与原理
一、hbase与列式存储
hbase最早起源于谷歌的一篇bigtable的论文,它是由java编写的、开源的一个nosql数据库,同时它也是一个列式存储的、支持分布式(基于hdfs)的数据库。什么是列式存储呢?简单来讲就是:传统的关系数据库几乎都是行式存储的,这种存储的特点是,将每一行的数据连起来进行存储;而列式存储是将每一列的数据连起来进行存储的。
列式存储相对于行式存储有哪些优点呢?
1.压缩空间:一张表里面,我存储的数据可以是非常松散的,就是说这一列可以有值也可以没有值,没有值就不会占用空间,而行式存储不行,它的结构非常规范,就算是某一列不赋值,那么这一行的这一列空间也是占用的,而且后期如果我想对某张表扩张字段的话,前面的的数据都必须强制开辟这个字段的存储空间。
2.查询性能:行式存储在查询的时候若我们制定某一个字段进行查询,他会遍历这一行的所有字段,然后找到匹配的字段进行返回,这样是很耗费io的,而列式存储由于它本来就是按列来进行数据存储的,就是说不同的列的数据是存储在不同地方的,所以检索指定列的时候只需要找到对应的列存储的位置,然后针对性检索就行了。
二、hbase的表结构
既然hbase是一个数据库,那么必然会有表的概念,它也有行键和列名的概念,不过与传统关系数据库不同的是它引入了列族的概念。
hbase的表分为两类,一类的系统表(又称meta表),另一类是用户表。meta表由系统创建与维护,主要存储表和分区的元数据信息,用户权限等。而用户表是我们自己创建的表,我们用户用来存储业务数据的表。
hbase的表里面有很多概念:行、列、行键、单元格、值、时间戳等。
如下图所示是一张hbase表,rowkey就是行键的概念,一行只有一个用来作为唯一标示。同时下图有两个列族,cf1和cf2,在它们下面又各有两个列,分别是name/age和sex/class,每一个行可以有多个时间戳标示不同的版本,例如下面的00001就有3个不同的时间戳版本,而hbase在查询的时候默认是获取最新的时间戳版本的数据。由rowkey、列(clomun)、timestamp可以确定一个唯一的单元格,如00001的t1时间的name是zhangsan。
同时我们可以看到有些列里面是没有值的,而hbase只对于有值的列存储进文件系统。
这里有一个rowkey排序的问题,hbase是根据rowkey的字节值进行数据排序的,且rowkey一般都是字符串形式存储的,存储的时候会将字符串转换为二进制流。也就是说,对于这里的rowkey00001和00002来说,00001是排在00002前面的。同时由于这么一个排序的问题,如果rowkey的设计不合理的话,很有可能会导致hbase的热点问题。
三、hbase的表存储
下图是hbase的一个table的存储结构,一个table有一个或者多个region组成,这也是hbase能够支持分布式存储的重要原因。同时一个region里由一个或者多个列族组成,一个列族有一个store实体组成,store实体里面有memstore、hfil,memstore是内存实体,hfile是实际的存储物理文件,hfile里面又由多个block组成,block里面存储的就是单元格数据cell。
region
如果是单机的话,所有行和列组成的单元格数据全部存储在一张表中就可以了,但是hbase为了支持集群分布式,就必须把一张很大的表拆分成多个region。每个region都有一个起始的rowkey和一个结束的rowkey来定义它的边界。同时每个region里面存储的那些rowkey都会保存在hbase的meta表中,查询的时候可以通过meta数据快速定位到需要查询的rowkey数据在哪个region里面。hbase里面有一个regionserver的角色,每个region会被分配到各自的regionserver中,这个是有hbase的负载均衡器自动完成的。同时当某个region很大的时候,它是可以分裂的,当然如果有需要,多个小的region也是可以合并的。
列族
列族是hbase独有的概念,在同一个region里面,不同的列族的数据会存储在不同的文件中。而列族如何分配,可以根据存储的数据的类型来决定,不同类型的数据可以存储在不同的列族中,如文本数据和图片数据就可以分开存储。
但是列族数量不宜过多,因为有一个列族就会有一个store,而region达到一定的大小之后就会进行分裂,这个时候列族过多就会出现问题。
例如:一个region里面有列族a和列族b,a有1000万数据,而b有10万数据,当region到达设定的阈值之后开始执行分裂,假设分裂为10份。那么对于列族a来说每一份就是有100万数据,但是对于b来说每一份就只有1万数据,那么当去检索b的数据的时候就需要遍历很多region从而导致性能降低。
store
一个store对应一个列族。store对象由memstore和hfile组成,memstore是数据写入的缓存区,而hflie是物理文件。数据写进来的时候首先进入到memstore里面,当memstore达到一定的阈值的时候hfile就会被创建。
block
hflie是由block组成的,这里的block与hdfs的block不同,一个hdfs的block可能会包含多个hfile的block。
四、hbase的角色
hbase在集群的情况下主要有两个角色:hmaster和regionserver。
hmaster
职责:1.region分配 2.负载均衡 3.regionserver恢复 4.监控region分裂 5.追踪活跃或者宕机的服务器
regionserver
regionserver是托管并且服务region以及hbase数据的应用程序。
如下图所示是一个9台的hbase集群,其中3台主机,6台从机。主机上面运行hmaster,hdfs的nn服务,以及zk服务,而从机上面运行regionserver服务以及hdfs的dn服务。我们连接hbase进行读写的时候都是先连接主机的zk,然后zk找到对应的master服务器,然后master服务器通过meta数据找到数据在哪个region上面,然后找到这个region在具体哪个regionserver上面并且建立连接,由regionserver再执行数据操作。
五、总结
关于hbase的概念呢以及存储结构就写这些好了,其实上面还有很多东西没写到,比如分裂合并的流程,读写流程什么的,同时我们在实际应用hbase的时候也有很多技巧,比如rowkey设计,二级索引等,如果不懂hbase的原理的话,在使用的时候经常会踩很多坑,如果有写的不对的地方也请大家多多指正,谢谢。