HBase是大数据NoSQL领域里非常重要的分布式KV数据库,是一个高可靠、高性能、高伸缩的分布式存储系统,目前国内知名公司都有在大规模使用,社区也非常活跃。本文就是学习HBase的敲门砖,主要从以下几个方面解读HBase。
HBase是Google的BigTable的开源实现,底层存储引擎是基于LSM-Tree数据结构设计的。写入数据时会先写WAL日志,再将数据写到写缓存MemStore中,等写缓存达到一定规模后或满足其他触发条件才会flush刷写到磁盘,这样就将磁盘随机写变成了顺序写,提高了写性能。每一次刷写磁盘都会生成新的HFile文件。可以参考如下的原理图:
随着时间推移,写入的HFile会越来越多,查询数据时就会因为要进行多次io导致性能降低,为了提升读性能,HBase会定期执行compaction操作以合并HFile。此外,HBase在读路径上也有诸多设计,其中一个重要的点是设计了BlockCache读缓存。这样以后,读取数据时会依次从BlockCache、MemStore以及HFile中seek数据,再加上一些其他设计比如布隆过滤器、索引等,保证了HBase的高性能。
关于HBase的数据模型,和关系型数据类似,包括命名空间(namespace)、表、行、列、列族、列限定符、单元格(cell)、时间戳等,具体概念比较好理解就不多解释了。而HBase在实际存储数据的时候是以有序KV的形式组织的。
参考上图,这里重点从KV这个角度切入,Value是实际写入的数据,比较好理解。其中Key则是由Rowkey、Column Family : Column Qualifier、Timestamp、Type等几个维度组成,其中rowkey是HBase的行键;column family(列族)与qualifier(列限定符即列名)共同组成了HBase的列;timestamp表示的就是数据写入时的时间戳,主要用于标识HBase数据的版本号;type代表Put/Delete的操作类型,说明一点,HBase删除是给数据打上delete marker,在数据合并时才会真正物理删除。此外,HBase的表具有稀疏特性,一行中空值的列并不占用任何存储空间。
HBase并不是行式存储,也不是完全的列式存储,而是面向列族的列族式存储。前面也提到了,HBase的每一列数据在底层都是以 KV 形式存储的,而针对一行数据,同一列族的不同列的数据是顺序相邻存放的,这种模式实际上是行式存储;而如果一个列族下只有一个列的话,就是一种列式存储。因此我们可以说HBase是一种列族式存储。
默认情况下HBase只对rowkey做了单列索引,所以HBase能通过rowkey进行高效的单点查询及小范围扫描。HBase索引还是比较单一的,通过非rowkey列查询性能比较低,除非对非Rowkey列做二级索引,否则不建议根据非rowkey列做查询。
HBase的二级索引一般是基于HBase协处理器实现,目前比较成熟的方案可以使用Phoenix,可以参考笔者最近的另一篇文章:HBase 集成 Phoenix 构建二级索引实践,Phoenix不仅能够为HBase提供二级索引能力,还扮演着HBase的SQL层,增强了HBase即席查询的能力。
每个组件都有它的强项和弱项,HBase也有它擅长与短板之处。
优点:
缺点:
HBase经常应用在订单/消息存储、用户画像、搜索推荐、社交Feed流、安全风控、以及物联网时序数据等诸多场景。社区也写过HBase应用场景的相关文章:再谈HBase八大应用场景,可以参考。
如果你的场景里需要存储海量数据,并发读写非常高,而且并不需特别复杂的数据分析,那么强烈建议你使用HBase。