Hbase架构

最近项目中用到了Hbase,其作为一款NoSQL产品,采用列式存储,适合存储非结构化/半结构数据,为了支持大规模数据集及扩展性,弱化了ACID,牺牲了事务的部分功能。Hbase是Hadoop生态体系中的一部分,底层存储是分布式文件系统HDFS。HBase and MapR-DB: Designed for Distribution, Scale, and SpeedAn In-Depth Look at the HBase Architecture这两篇文章写的很好,把hbase的适用场景、架构设计及关键实现清晰易懂的描述出来,推荐读下这两篇博客,当然,时间充裕的话最好还是去看官方文档,写的非常详细。本文的目的是提炼一下其中的关键点。

Hbase和RDBMS

传统的RDBMS(MySQL),其特点和其名字一样,是『关系型』的,意味着存储的数据模型需要严格符合schema,表设计需要符合范式,支持完整的事务功能(ACID)来确保数据一致性,支持复杂的联合查询。但是其设计初衷是在单节点,尽管可以对数据进行sharding水平拆分来构建集群模式,这种模式下的扩展性和读写性能有时候并不能满足海量数据的读写,而且一些join查询往往会成为瓶颈。

Hbase就是列式存储,将相关联的数据都存储在一块,方便读写,而不是像RDBMS一样将数据分散存储,再通过join查询进行聚合,另一方面Hbase牺牲一定的事务性,只支持单行,这样可以增大吞吐量,提高读写性能。

Hbase不是用来替代传统的RDBMS,两种数据库都有其各自的适用场景。如果需要完整的事务功能、复杂查询(SQL)、二级索引,则选择RDBMS。如果是存储大规模非结构/半结构数据,则推荐使用Hbase。

Hbase数据模型

Hbase是列式存储,核心的是其唯一主键RowKey,数据的分布和高性能读写都靠RowKey来完成的,内部都是按RowKey进行有序存储,Hbase将连续的RowKey进行拆分,分散到不同的服务器(Region Server)中,所以RowKey的合理设计关系到hbase的读写性能。而真正的数据则是存储在一个个Column之中,不同的Column可以组成ColumnFamily。 Hbase是稀疏存储,所以如果有的列没有值则不存储。Hbase中最小的存储单元是Cell:

Table:RowKey:ColumnFamily:Column:Timestamp -> Value

Hbase中的Table可以通过RowKey拆分到不同的server上,同一个RowKey又可以根据ColumnFamily存储在不同的文件中,最终通过5要素定位到value。Cell中timestamp是版本号,数据的增加和修改都是一条新纪录,只不过版本号不同,数据的删除则通过标记实现,查询的时候进行过滤。

Hbase架构

Hbase架构中的角色主要包括Client、Zookeeper、Hmaster、Region Server。

Hbase读写

写过程

Hbase写过程包含两步,首先将数据写入WAL,其次将数据写入MemStore,成功后可以返回ack至Client。

Region Flush

当MemStore写满后,需要进行刷盘操作,将MemStore flush到HFile。由于每一个ColumnFamily对应一个MemStore,而当一个MemStore满时,会flush当前Region中所有的MemStore,所以需要限制ColumnFamily的个数。在MemStore Flush时,会在HFile的meta字段存储最大的WAL序列值,这样系统就知道目前持久化到哪里了,系统恢复时可以从这个sequence开始。HFile是顺序写的,避免了频繁的磁盘查找。

HFile索引

HFile建立了类似于B+数的多级索引,可以让避免查找数据时扫描整个HFile,而且每个HFile也存了Bloom Filter和Time Range信息,可以快速筛选不在HFile中的RowKey。

读过程

由于归属于同一个RowKey的Cell可能会在多个地方(已经持久化的HFile,最近更新的MemStore,最近读过的BlockCache),所以在进行读操作时需要进行合并操作,过程如下:

Hbase压缩

由于每次MemStore容量满时都会flush生成新的HFile,所以HFile会越来越多,对读性能造成影响。Hbase的策略是进行压缩,将小文件合并成大文件,分为Minor Compaction和Major Compaction。Minor Compaction是轻量级的压缩工作,把HFile通过归并排序合并成稍微大点的HFile。而Major Compaction则是重量级的,将Region中所有HFile都合并成一个,并删除过期和废弃的Cell。但是Major Compaction会造成大量的网络IO,所以可以放在系统空闲的时候进行。

Region拆分和负载均衡

当一个Region增长到一定规模时,出于负载均衡的考虑,会将其拆分成两个ChildRegion,ChildRegion会向HMaster注册,如果一个RegionServer负载过高,HMaster会将Region分配到其他的RegionServer中。这样会导致RegionServer和本地数据(HFile)不在一起,会在下一次Major Compaction时将HFile移到当前的RegionServer。

Powered by Jekyll and Theme by solid