Hbase底层原理浅析

Posted 我就是程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hbase底层原理浅析相关的知识,希望对你有一定的参考价值。


团队文化:进取,分享,快乐,责任!

团队愿景:做最好的产品,打造有影响力的团队!


Hbase简介                                                                                                                           

Hbase是一个分布式的、面向列的开源数据库,是Apachehadoop项目的子项目。不同于一般的数据库,Hbase是一个非常适合于非结构化数据以及海量数据存储的数据库。本文从现行数据库存在的问题,Hbase数据库存储模型及体系结构,Hbase简单使用以及最佳实践者四个角度对Hbase数据库进行简要叙述,使大家对Hbase数据库从底层有一个清晰的认识,以方便后续的使用。目前京东雨人医药同步系统同步日志的信息,处方药订单事件轨迹的信息等都在使用Hbase进行存储。

 

现行数据存储方式

现行数据库数据存储方式主要包括行式存储和列式存储,在介绍列式存储的优势之前,想要先对行式存储做一个简要说明。通过对比来展现列式存储的优势。

行式存储:即以行作为单元对数据进行存储。应用在当前几乎所有关系型数据库,例如mysqloracle等,历史非常悠久,使用非常广泛。

1)行式存储优点:在建表时,已经做规定好数据长度以及数据类型,结合索引可以进行非常高效的查询。

2)行式存储缺点:1)浪费存储空间:一个表可能有50多个字段,但是经常用到的可能只有两三个,那么用行式存储这种组织方式,势必导致存储空间存在一定的浪费。2)巨量磁盘IO:在进行数据查询的时候,为了存取速度,数据库会一次性读取若干条数据交给客户端(注:此处的客户端值数据库服务器上的客户端,而非应用服务器上的客户端,下同),在客户端进行筛。例如,在执行select order_status from rx_info ,我们需要的只是order_status这个字段,但是数据库却把50个字段的数据全部交给客户端,客户端再从整行数据中选出order_status(订单状态),这个操作会带来巨量的磁盘IO。所以在对少许列查询时,关系型数据库优势不大。3)对于传统的行式数据库,在进行海量数据的存储及检索时,几乎是无能为力的。

Hbase列式存储则通过另一种数据组织形式解决了行式存储的缺点,下面透过“逻辑模型”、“物理模型”、“存储模型”三个存储模型,展示出Hbase强大的存储优势及查询优势。

 

Hbase存储模型及体系结构

逻辑模型:表示数据在逻辑概念上的存储方式,逻辑模型的概念主要为了我们能对数据组织方式方便的进行理解。结合下标,对行、行键、列、列簇、时间戳进行说明。行:即广义理解的行。行键(123.abc.DEF):类似于关系型数据库的主键,不存在两个行键完全相同的行建。列(B):广义的列,但是不能脱离列簇而单独存在,例如列簇B存在两列,其中列”bbb”的值为”eee”。列簇(Colums “B”):列的集合,每一个列簇就是一个文件。时间戳(Timsstamp):数据插入到Hbase表中的时间,取数据库的时间。天然存在的,只要创建Hbase表就会有时间戳概念。

Hbase底层原理浅析

物理模型:表示数据实际存储时的方式。列簇:单独存储一系列列的文件。Hbase在进行数据存储时,会前进行了大小比较,最终是按照行键进行存储的(Mysql存储Innodb搜索引擎按照主键顺序存储。参考:https://zhuanlan.zhihu.com/p/39812854)。数据真实的存储方式见下图。


Hbase底层原理浅析

存储模型:表示数据在分布式环境下的存储方式,只有明白这个知识点,才能设计出搜索效率较高的行键。首先,Hbase面对的数据量是TP级别的,相同量级数据在mysql中直接宕机,在oracle中会非常慢。而Hbase如何做到高效的存储,与他的存储模型有密不可分的关系。Hbase表在行的方向上分割为多个Region,一个region[startKey,endKey]表示,每个region分散在不同的region server上面。例如0~10000region1上找,10001~20000region2上找依次类推,这就实现了高并发快速查询。

Hbase底层原理浅析

体系结构:表示客户端通过什么样的请求路径来获取所需要的数据。首先,我们称Hbase主节点称为master,从节点称为region server。我们的请求首先发送到master,然后在由master找到对应的region server。这个过程涉及到Hbase中非常重要的两个表:-ROOT-表和.META.表。

.META.表:记录了用户表中的Region信息,.META.可以有多个region

-ROOT-表:记录了.META.表中的Region信息,-ROOT-中只有一个region Zookeeper中记录了-ROOT-表中的location

Zookeeper:客户端访问用户表数据之前,首先需要访问zookeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到准确的位置去获取数据。

总结:逻辑模型清晰的向用户展示了Hbase对于数据的管理方式,实现了列式存储,可以用最小的代价获取所需要的数据;物理模型展示了Hbase数据库如何实现对存储空间最大化的利用;存储模型展示了Hbase如何对数据进行分片管理,解决了大数据存储及海量数据搜索的问题;体系结构则向我们展示了Hbase再进行高效的数据检索时的步骤。

 

简单使用

结合雨人医药同步系统对操作日志的存储,简单说明Hbase的存储方式

Rowkey设计:“时间戳:仓库id:业务id:消息主题:uuid”。


通过 put.add方法加载数据,顺序为列簇(info),列名(storeId opicusinessId),value内容。创建Put类方法传rowkey

Put put = newPut(Bytes.toBytes(rowKey));  

put.add(Bytes.toBytes(info),Bytes.toBytes(storeId), Bytes.toBytes("631"));

put.add(Bytes.toBytes(info),Bytes.toBytes(topic), Bytes.toBytes("product"));

put.add(Bytes.toBytes(info), Bytes.toBytes(businessId), Bytes.toBytes("123"));

 

:通过传递将要删除的行的rowKey的字节数组格式,实例化Delete类。也可以通过构造时间戳和Rowlock

Delete delete =new Delete(toBytes(rowKey));

delete.deleteColumn(Bytes.toBytes(info),Bytes.toBytes(storeId));

delete.deleteFamily(Bytes.toBytes(info));

:主要有get操作、scan操作、filter过滤器。其中get操作值获取一条记录,scanfilter结合使用获取多条记录。

GET查询方式

Get get=newGet(rowkey.getbytes());

Resultget1=htable.get(get);

get1.getValue(Bytes.toBytes(info),Bytes.toBytes(storeId));


Scan+fiter方式

获取开始行为rowkey1,结束行为rowkey2,行键包含product的数据

Scan scan = new Scan();

Filter filter=new RowFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator

(":" +product + ":"));

scan.setStartRow(rowkey1.getBytes());

    scan.setStopRow(rowkey2.getBytes());

    scan.setFilter(filter);


 

最佳实践

分页Hbase分页分为服务端分页和客户端分页。服务端分页使用的是FilterPage过滤器,他表示的是一个偏移量。客户端分页是将所有符合查询条件的数据一次性取出,在客户端利用程序进行分页。所以当想获取某一页的数据时,单靠服务端分页方式不容易实现,当时海量数据时,在客户端分页方式势必会对客户端造成不小的压力。作者结合两者的优势,每次从服务器获取pageSize*page调数据。在将数据在客户端进行分页。面对海量数据,可以不必获取海量的数据,又能达到分页的效果。

查询效率:对于特定的数据,尽量用get的方式,不建议用scan+filter的方式进行查询,因为filter过滤器的查询效率非常低。性能并不能满足要求。如果批量获取,一定要为scan赋值开始行和结束行来缩短查询范围。

Rowkey设计原则:满足长度原则、散列原则、唯一原则

长度原则:建议是越短越好,不要超过16个字节。原因如下。

数据的持久化文件HFile中是按照KeyValue存储的,如果Rowkey过长比如100

字节,1000万列数据光Rowkey就要占用100*1000=10亿个字节,将近1G数据,这会极大影响HFile的存储效率;

MemStore将缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此Rowkey的字节长度越短越好。

目前操作系统是都是64位系统,内存8字节对齐。控制在16个字节,8字节的整数倍利用操作系统的最佳特性。

散列原则:

如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个Regionserver实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有新数据都在一个 RegionServer上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别RegionServer,降低查询效率。

唯一原则:

必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。















 


以上是关于Hbase底层原理浅析的主要内容,如果未能解决你的问题,请参考以下文章

跨平台语言的底层原理浅析

浅析Json底层

hbase的底层原理

HBase底层存储原理

Hbase底层原理

通过子类实现KVO,浅析KVO底层原理