当前位置: 首页 > 科技观察

了解Hbase列式数据库

时间:2023-03-20 19:32:37 科技观察

1。什么是Hbase?HBase是一个高可靠、高性能、面向列、可扩展的分布式存储系统,目标是存储和处理大数据。HBase是GoogleBigtable的开源实现,区别在于:GoogleBigtable使用GFS作为文件存储系统,HBase使用HadoopHDFS作为文件存储系统;GoogleBigtable使用Chubby作为协作服务,HBASE使用Zookeeper作为协作服务。Hbase是一个面向列的分布式存储系统。它的优点是可以实现高性能的并发读写操作。同时,Hbase还对数据进行了透明拆分,使得存储本身具有横向可扩展性。2、Hbase的数据模型是什么?HBase的数据存储模型包括以下几个概念:行:一行数据包含唯一标识Row-Key、多个列和对应的值。在HBase中,表中的所有行按照Row-Key字典顺序(二进制位移计算)从小到大排序。column:与关系数据库中的列不同,HBase中的列由两部分组成:columnfamily(列族)和qualifier(列名)。列族需要在创建表的时候指定,用户不能随意增减。列族下可以设置任意数量的限定符,所以可以理解为HBase中的列是可以动态增加的。cell:一个cell,一个由五个元组(row,column,timestamp,type,value)组成的结构体,其中type表示Put/Delete等操作的类型,timestamp表示这个cell的版本。这个结构体在数据库中实际存储在KV结构体中,其中(row,column,timestamp,type)为K,value字段对应KV结构体的V。timestamp:每个cell在写入HBase时默认会分配一个时间戳作为cell的版本。HBase支持多版本特性,即同一个Row-Key和column下可以有多个值,这些值使用时间戳作为版本号。HBase是一个面向列的数据库,其中表按行排序。表架构定义只能是列族,即键值对。一个表可以有多个列族,每个列族可以有任意数量的列。后续列的值连续存储在磁盘上。表中的每个单元格值都有一个时间戳。综上所述,在HBase中:表是行的集合,行是列族的集合,列族是列的集合,列是键值对的集合。表1逻辑存储视图表2物理存储视图HBase的逻辑存储视图由rowkey、timestamp、columnfamily组成类似二维表的结构,但在实际存储中,存储在数据库中的数据是基于列族的存储单元是将行数据完全分组到列族中。3、Hbase的存储架构是怎样的?图1Hbase物理存储架构Region是HBase中分布式存储和负载均衡的最小单元,不同的Region分布到不同的RegionServer上,如表1和表2所示,有多个Region,这些Region分布在不同的RegionServer上。Region虽然是分布式存储的最小单位,但并不是最小的存储单位。Store是最小的存储单元。一个Region由一个或多个Stores组成,每个Store存储一个ColumnFamily;每个Store由一个MemStore或0到多个Hfiles组成;MemStore存放在内存中,HFile存放在HDFS中。Hbase在数据存储过程中,涉及到的物理对象分为以下几种:HMaster:负责DDL创建或删除表,同时只能存在一个activemaster。Zookeeper:判断HMaster的状态,记录MetaTable的具体位置;Region:BigTable的一个shard,记录key的起止;WAL:write-aheadlog,持久化顺序存储,由一个RegionServer维护一组WAL;RegionServer:RegionServer维护多个region,region包含MemStore和多个HFile;MemStore:对应BigTable的一个ColumnFamily,存在于文件缓存中,有文件句柄;BlockCache:读取缓存,存放在内存中;(行键->行);HFiles:从MemStoreFlush出来的文件是持久化的,存储在HDFS的DataNode中。Flush每次生成一个新的HFile文件,该文件包含有序的键值对序列。4、Hbase如何读写数据?图2Hbase读写示意图数据写入流程(如左图):客户端先从Zookeeper中找到meta表的region位置,然后读取meta表中的数据,meta表中存放的是用户的region信息桌子。根据命名空间、表名和Row-Key信息。找到写入数据对应的region信息,找到这个region对应的regionServer,然后发送请求。将数据分别写入HLog(writeaheadlog)和memstore。memstore达到阈值后,将数据刷入磁盘,并生成storeFile文件。删除HLog中的历史数据。数据读取流程(如右图):客户端先连接Zookeeper;从Zookeeper中找到meta表的region位置,即meta表的数据存放在某个HRegionServer上;客户端与这个HRegionServer建立连接,然后读取元表中的数据;所有用户表的region信息都保存在meta表中,我们可以通过scan'hbase:meta'查看meta表信息。根据命名空间、表名和Row-Key信息查询。找到写入数据对应的区域信息。找到这个region对应的regionServer发送请求,找到对应的region。先从memstore中查找数据,如果没有,则从BlockCache中读取。如果在BlockCache中没有找到,则从StoreFile中读取。从storeFile读取数据后,不是直接将结果数据返回给客户端,而是先将数据写入BlockCache,以加快后续查询;然后将结果返回给客户端。5、Hbase是什么类型的存储引擎?首先需要确定的是Hbase的存储引擎是LSM-Tree(可以参考之前的文章:DB存储引擎知识系列三:LSM-Tree存储引擎详解)。通过上一篇对LSM-Tree的介绍,我们知道LSM-Tree与B+Tree相比,最大的特点是通过牺牲部分读性能,利用分层合并的思想,小树合并成一棵大树,将无序数据合并成有序数据,然后统一刷入磁盘,大大提高了写入性能。那么,当HBase应用于LSM时,Memstore就是LSM中的Memtable,也就是C0层的小树写入,HFiles就是LSM中的SSTables,也就是Cn层合并后的树的顺序写入。另外,Hbase在实现Hbase的时候,其实有自己独到的特点:MinorvsMajorCompaction:MinorCompaction,根据配置策略,自动检查小文件,合并成大文件,从而减少文件碎片,但它不立即删除旧的HFiles;MajorCompaction,无论每个CF中有多少个HFile,最终都会将HFile合并成一个大的HFile,并删除所有旧的HFile,即CF和HFile最终会变成一对一的关系。BlockCache:除了MemStore(即MemTable),HBase还提供了另一种缓存结构BlockCache。BlockCache本质上是将热数据维护在内存中,以避免磁盘I/O。当然,即使BlockCache找不到数据,它仍然可以去MemStore中查找。只有当两边都没有数据时,才会读取内存中的数据。HFile索引被寻址到硬盘以进行I/O操作。HBase将BucketCache和LRUBlockCache一起使用,称为CombinedBlockCache。系统主要将IndexBlock存放在LRUBlockCache中,DataBlock存放在BucketCache中。所以一次随机读需要先在LRUBlockCache中找到对应的IndexBlock,然后再去BucketCache中找到对应的数据块。HFile:HFile的数据结构也是Hbase的一个重要改进。图中展示了HFile的数据结构,主要包括四部分:数据块、头信息、索引信息、地址信息。索引是HFile内置的B+树索引。当RegionServer启动,HFile打开时,索引会被加载到BlockCache,即内存中;KeyValues存放在增长队列中的数据块中,数据块可以指定Size,默认为64k。数据块越大,顺序检索能力越强;数据块越小,随机读写能力越强,需要权衡。6、Hbase与传统RDBMS有什么区别?表4列式数据库和关系数据库之间的差异描述了HBase和RDBMS之间的许多差异。那么什么时候最需要HBase,或者说HBase能否替代原来的RDBMS呢?对于这个问题,我们要时刻牢记,HBase并不是适用于所有场景,其最终目的也不是要完全取代RDBMS,而是对RDBMS的重要补充。在考虑将HBase作为备选产品选择时,我们需要考虑以下关键问题。业务场景是否符合非ACID事务原则?数据的业务特性是否需要复杂的查询,比如SQL实现的复杂的join、sorts、复杂的条件?读取列族数据是否可以更高效的实现业务场景,数据是否可以用字符表示?数据量够用Hbase列式数据库吗?是否可以找到合适的行键?RandomRow-keys适合频繁写入,orderedRow-keys适合大量读取。7、Hbase是如何解决热点问题的?HBase中的行是按照Row-Key的字典顺序排序的。这种设计优化了扫描操作,并且可以将相关行存储在附近的位置以便于扫描。然而,糟糕的Row-Key设计是热点的根源。一旦Row-Key设计与业务场景不匹配,大量访问会导致热点区域所在的单机超出自身容量,造成性能下降甚至不可用,同时也会影响到同一个区域的其他区域相同的区域服务器。那么如何避免此类问题呢?通常有以下设计思路可供参考:Reverse:将Row-Key字符串的可变部分放在前面,相对固定的部分放在后面。这样会打乱Row-Key的顺序,在一定程度上降低批量写入数据的性能,但会减少读取时的热查询,通过牺牲部分写入性能来提高读取的性能。Prefix:为每个Row-Key添加一个随机字符前缀,使数据分散在多个不同的Region中,达到Region负载均衡的目的。最终消除局部热点,解决热点读写问题。Hash:通过哈希重新设计Row-Key,让数据分散在不同的Region中,效果优于prefix方式,因为在读取的时候,可以通过计算hash损失来减少读取的性能。既解决了热点问题,又不需要消耗过多的读性能。