HBase工做原理

HBASE原理

1、原理

一、物理存储

1.hregion

    hbase表中的数据按照行键的字典顺序排序,hbase表中的数据按照行的的方向切分为多个region。mysql

    最开始只有一个region随着数据量的增长,产生分裂,这个过程不停的进行。一个表可能对应一个或多个region。sql

    region是hbase表分布式存储和负载均衡的基本单元,一个表的多个region可能分布在多台HRegionServer上。数据库

2.Store

    region是分布式存储的基本单元,但不是存储的基本单元,其内部还具备结构。一个region由多个Store来组成。缓存

    有几个store取决于表的列族的数量,一个列族对应一个store。之因此这么设计,是由于一个列族中的数据每每数据很相似,方便进行压缩,节省存储空间。安全

3.memStore

    表的一个列族对应一个store,store的数量由表中列族的数量来决定。一个store由一个memstore和零个或多个storefile组成。服务器

    memStore负责保存内存中的数据。网络

4.Storefile

    storefile其实就是hdfs中的hfile只能写入不能修改,因此hbase写入数据到hdfs的过程实际上是不断追加hfile的过程。架构

    hfile的结构:负载均衡

 

    HFile分为六个部分:分布式

    Data Block段–保存表中的数据,这部分能够被压缩

    Meta Block 段(可选的)–保存用户自定义的kv对,能够被压缩。

    File Info段–Hfile的元信息,不被压缩,用户也能够在这一部分添加本身的元信息。

    Data Block Index段–Data Block的索引。每条索引的key是被索引的block的第一条记录的key。

    Meta Block Index段(可选的)–Meta Block的索引。

    Trailer–这一段是定长的。保存了每一段的偏移量,读取一个HFile时,会首先 读取Trailer,Trailer保存了每一个段的起始位置(段的Magic Number用来作安全check),而后,DataBlock Index会被读取到内存中,这样,当检索某个key时,不须要扫描整个HFile,而只需从内存中找到key所在的block,经过一次磁盘io将整个 block读取到内存中,再找到须要的key。DataBlock Index采用LRU机制淘汰。

    HFile的Data Block,Meta Block一般采用压缩方式存储,压缩以后能够大大减小网络IO和磁盘IO,随之而来的开销固然是须要花费cpu进行压缩和解压缩。

    目标Hfile的压缩支持两种方式:Gzip,Lzo。

5.HLog(WAL log)

    WAL意为Write ahead log(http://en.wikipedia.org/wiki/Write-ahead_logging),相似mysql中的binlog,用来作灾难恢复之用,Hlog记录数据的全部变动,一旦数据修改,就能够从log中进行恢复。

    每一个Region Server维护一个Hlog,而不是每一个Region一个。这样不一样region(来自不一样table)的日志会混在一块儿,这样作的目的是不断追加单个文件相对于同时写多个文件而言,能够减小磁盘寻址次数,所以能够提升对table的写性能。带来的麻烦是,若是一台region server下线,为了恢复其上的region,须要将region server上的log进行拆分,而后分发到其它region server上进行恢复。

    HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是”写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue。

二、读写流程

1.hbase写入数据

    数据写入hbase时,先在hlog中记录日志,再修改memstore,而后直接返回成功。这样不须要真正等待写入hdfs的过程,因此很快。

    memstore内存有限,当写入数量达到必定的阈值的时候,就会建立一个新的memstore继续工做,而旧的memstore会用一个单独的线程将数据写出到storefile中,最终清空旧的memstore并在zookeeper中记录最后写出数据时间的redo point信息。

    因为storefile不能修改,因此数据的更新实际上是不停建立新的storefile的过程。

    这样多个storefile中可能存在对同一个数据的多个版本,其中部分旧的版本实际上是垃圾数据,时间过长,垃圾数据就可能不少,浪费磁盘空间。

    因此当达到必定的阈值的时候,master会自动合并storefile,在合并的过程当中将垃圾数据清理。而当合并出来的文件达到必定程度时,再重新进行切分,防止文件过大。

    虽然看起来是小变大再变小,可是通过这个过程垃圾数据就被清理掉了。因此store中的数据,实际上是memstore和storefile来组成的。

    而memstore因为是内存中的数据,一旦断电就会丢失。为了解决可能的意外形成数据丢失的问题,hbase在整个hregionserver中,经过记录hlog来保存了全部数据操做的记录。当hbase启动时,会检查zookeeper中的redopoint信息,从hlog中恢复这个时间点以后的数据,解决内存中memStore数据容易丢失的问题。

    hlog文件在每台hregionServer中都有一个,全部这台机器中的全部HRegion都公用这个文件,这样整个机器的磁盘性能均可觉得这一个文件提供支持,提高文件的读写效率。

    hlog文件也是存储在hdfs中的,也是分布式存储的,保证了日志文件的可靠性。

2.hbase读取数据

    在查询数据时,先查找内存,若是内存中有当前键对应的数据,获取数据直接返回。

    若是没有在内存中找到数据,就去查找region对应的hfile,注意不是将全部hfile中的数据恢复到内存,而是查找每一个hfile的Trailer,经过trailer找到Data Block Index,若是在这里发现了要找的数据,经过索引找到Data Blocks中对应的Data Block,将Data Block数据送回内存组装,最终将多个hfile中获取到的数据进行合并,而后返回最新版本的数据。

    因为hbase中的数据自然排序,再加上底层索引,整个查询也能够很是的快。

3.hbase中region的寻址

    在hbase的hbase名称空间下有一张meta表,其中存放了表和region和regionSever之间的对应关系信息,这个表很特别,规定meta表只能有一个region。而且这个meta表的这个region的位置信息被存放在了zookeeper的meta-region-server节点下。

    在客户端从hbase中查找数据时,须要先联系zookeeper找到meta表对应的region的位置,链接这个位置读取到meta表中的信息,才能知道要查询的表、表的region和region对应的regionServer的信息。再根据这些信息链接真正要查询的表对应的region的regionServer进行读取,这个过程就称之为region的寻址过程。

    这样的寻址过程是至关耗费时间的,为了提升性能,客户端一般会缓存以前已经知道的region寻址信息,当客户端再次读取同一个表中的数据时,能够经过本地缓存的region地址信息,直接定位读取,提升效率。

 

三、存储系统三种结构

1.hash存储

    哈希存储引擎是哈希表的持久化实现,支持增、删、改以及随机读取操做,但不支持顺序扫描,对应的存储系统为key-value存储系统。对于key-value的插入以及查询,哈希表的复杂度都是O(1),明显比树的操做O(n)快,若是不须要有序的遍历数据,哈希表就是your Mr.Right。

2.B树

    B+树 B-树 B*树

    B树存储引擎是B树的持久化实现,不只支持单条记录的增、删、读、改操做,还支持顺序扫描(B+树的叶子节点之间的指针),对应的存储系统就是关系数据库(Mysql等)。

3.LSM树

    LSM树(Log-Structured Merge Tree)存储引擎和B树存储引擎同样,一样支持增、删、读、改、顺序扫描操做。并且经过批量存储技术规避磁盘随机写入问题。固然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提升写性能。

    经过以上的分析,应该知道LSM树的由来了,LSM树的设计思想很是朴素:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操做批量写入磁盘,不过读取的时候稍微麻烦,须要合并磁盘中历史数据和内存中最近修改操做,因此写入性能大大提高,读取时可能须要先看是否命中内存,不然须要访问较多的磁盘文件。极端的说,基于LSM树实现的HBase的写性能比Mysql高了一个数量级,读性能低了一个数量级。

    LSM树原理把一棵大树拆分红N棵小树,它首先写入内存中,随着小树愈来愈大,内存中的小树会flush到磁盘中,磁盘中的树按期能够作merge操做,合并成一棵大树,以优化读性能。

 

    以上这些大概就是HBase存储的设计主要思想,这里分别对应说明下:

    由于小树先写到内存中,为了防止内存数据丢失,写内存的同时须要暂时持久化到磁盘,对应了HBase的MemStore和HLog。

    MemStore上的树达到必定大小以后,须要flush到HRegion磁盘中(通常是Hadoop DataNode),这样MemStore就变成了DataNode上的磁盘文件StoreFile,按期HRegionServer对DataNode的数据作merge操做,完全删除无效空间,多棵小树在这个时机合并成大树,来加强读性能。

四、hbase系统架构:

    hbase中的老大叫hmaster,小弟叫hregionServer,客户端叫Client,Zookeepr为hbase提供集群协调。

 

1.client

    访问hbase保留一些缓存信息提高效率。

2.zookeeper

    保证任什么时候候集群只有一个HMaster。

    监控regionServer的状态,将其上线下线信息通知mater。

    存储meta表Region的地址。

    存储hbase的元数据信息。包括有哪些表、有哪些列族等等。

3.Master

    为RegionServer分配Region。

    为RegionServer进行负载的均衡。

    GFS上的垃圾回收。

    处理对Schema数据的更新请求。

4.RegionServer

    维护Master分配给它的region,处理对这些region的IO请求。

    负责切分在运行过程当中变得过大的region。

五、总结

1.为何hbase能够很快

1>从逻辑结构上来讲

    表按照行键进行了排序,并且加了索引,因此查询时能够很快定位。

    数据按照行键切分为多个HRegion,分布在多个RegionServer中,查询大量数据时,多个RegionServer能够一块儿工做,从而提升速度。

2>从物理结构上来讲

    HRegion是存活在RegionServer的内存中的,读写会很是的高效。

    还有HFile的支持保证大量的数据能够持久化的保存。

    数据最终落地到HDFS中,分布式的存储,保证数据段可靠性和可扩展性。

2.为何hbase能够存储不少数据

    基于hdfs,因此支持可扩展性,能够经过增长大量的廉价的硬件提升存储容量。

    按列存储,空的数据不占用空间,当存储稀疏数据时,不会浪费空间。

    按例存储,同一列的数据存放在一块儿,而同一列的数据通常都是一样的类型的内容类似的数据,能够实现很是高效的压缩,节省空间。

3.为何hbase的数据是可靠的

    基于hdfs,由hdfs的可靠性保证了hbase的可靠性,即数据能够有多个备份。

    利用zookeeper实现了HA(高可用集群),即便某一台机器挂掉另外的机器也能够很快的替换它。

4.hbase和hive和传统的关系型数据库的比较

    比起传统的关系型数据库,能够存储半结构化非结构化的数据,能够存储和处理更大级别的数据,提供高效的查询,对于稀疏数据的处理更好,具备更好的横向扩展性,免费开源性价比很高。可是不能支持很是好的事务特性,只支持行级的事务。只能经过行键来查询,表设计时难度更高。而mysql用来存储结构化的数据提供更好的事务控制。

    比起hive,hive只是在mapreduce上包了一层壳,本质上仍是离线数据的处理的工具,实时查询性能有限,本质上是一个基于hadoop的数据仓库工具,不能支持行级别的新增修改和删除。hbase能够提供实时的数据的处理能力,适用于在线数据查询处理,本质上是一种数据库工具。

2、HBase的表设计

    HBase表的设计会直接影响hbase使用的效率和使用的便利性。

    HBase表的设计主要是列族的设计和行键的设计。

一、列族的设计

    在设计hbase表时候,注意如下事项:

    1.列族不宜过多,越少越好,官方推荐hbase表的列族不宜超过3个。列族设计过多,会很是消耗内存。

    2.常常要在一块儿查询的数据最好放在一个列族中,尽可能的减小跨列族的数据访问。

    3.若是有多个列族,多个列族中的数据应该设计的比较均匀。

二、行键的设计

    hbase表中行键是惟一标识一个表中行的字段,因此行键设计的好很差将会直接影响将来对hbase的查询的性能和查询的便利性,因此hbase中的行键是须要进行设计的。

1.行键设计的基本原则

1>必须惟一

    行键必须惟一才能惟一标识数据。

2>必须有意义

    行键必须有意义,这样才能方便数据的查询。

3>最好是字符串类型

    全部语言平台针对字符串的操做是统一,数值类型在不一样的系统中处理的方式可能不一样。

4>最好具备固定的长度

    不一样长度的数据可能会形成天然排序时排序的结果和预期不一致。

5>不宜过长

    行键最多能够达到64KB,可是最好是在10~100字节之间,最好不要超过16字节,越短越好,最好是8字节的整数倍。

    底层存储是利用key-value存储的,行键会屡次出现,若是行键过长会致使大量存储空间被行键消耗掉。

2.行键的最佳实践

    综合来看如下两个原则是存在冲突的,因此在选择的时候只能使用其中之一,具体使用那个原则,要根据实际的业务以及集群的能力来考虑。

1>散列原则

    行键的设计将会影响数据在hbase表中的排序方式,这会影响region切分后的结果,要注意,在设计行键时应该让常常要查询的数据分散在不一样的region中,防止某一个或某几个regionserver成为热点。

    当出现热点数据的时候,会致使整个集群的服务器相继挂机,最终致使集群崩溃,即雪崩。

2>有序原则

    行键的设计将会影响数据在hbase表中的排序方式,因此一种策略是将常常连续查询的条件做为行键最前面的数据,这样一来能够方便批量查询。

上一篇:HBase简介及搭建

下一篇:HBase的Java API操做

相关文章
相关标签/搜索