HBase:分布式列式NoSQL数据库

网友投稿 656 2023-04-06

***:分布式列式NoSQL数据库

***:分布式列式NoSQL数据库

传统的ACID数据库,可扩展性上受到了巨大的挑战。而***这类系统,兼具可扩展性的同时,也提出了类SQL的接口。

***架构组成

HMaster节点

协调HRegionServer启动时HRegion的分配,以及负载均衡和修复时HRegion的重新分配。监控集群中所有HRegionServer的状态(通过与zookeeper的Heartbeat和监听ZooKeeper中的状态,并不直接和slave相连)Admin职能:创建、删除、修改Table的定义。

HRegionServer节点

存放和管理本地HRegion。读写HDFS,管理Table中的数据。Client直接通过HRegionServer读写数据

一个HRegionServer可以存放1000个HRegion(出自BigTable);***使用RowKey将表水平切割成多个HRegion,从HMaster的角度,每个HRegion都纪录了它的StartKey和EndKey(第一个HRegion的StartKey为空,最后一个HRegion的EndKey为空),由于RowKey是排序的,因而Client可以通过HMaster快速的定位每个RowKey在哪个HRegion中。

底层Table数据存储于HDFS中,而HRegion所处理的数据尽量和数据所在的DataNode在一起,实现数据的本地化;数据本地化并不是总能实现,比如在HRegion移动(如因Split)时,需要等下一次Compact才能继续回到本地化。

ZooKeeper集群是协调系统

存放整个***集群的元数据以及集群的状态信息(avalible/alive)。实现HMaster主从节点的failover,并在HRegionServer宕机的时候通知HMaster。

***的第一次读写

0.96以前的版本(参考BigTable)

***有两个特殊的表,ROOT表(唯一)和META表。其中,ROOT表的位置保存在ZooKeeper中,它存储了META表的RegionInfo信息。而META表 则存储了用户Table的RegionInfo信息,它可以被切分成多个HRegion。

从ZooKeeper读取ROOT表位置HRegionServer中根据请求的Root表和RowKey读取META表位置最后从该HRegionServer中读取META表的内容而获取此次请求需要访问的HRegion所在的位置读取内容。

所以需要3次读取才能获取目标HRegion的位置,然后第4次请求才能获取真正的数据。所以,一般客户端有ROOT表位置喝内容的缓存。

我们来看看为什么BigTable要选择三级索引结构,BigTable论文里面提到,一般每个HRegion大小为128M,每行META数据1KB。所以,三级索引可以索引2^34个HRegion,可以索引很大很大的数据了。但是如果只有二级索引,我们就只能索引16TB,在大数据情况下这是完全不够。

0.96后的版本

hbase:meta表

meta表存储了所有用户HRegion的位置信息,它的RowKey是:tableName,regionStartKey,regionId,replicaId等,它只有info列族,这个列族包含三个列,他们分别是:

regioninfo列是RegionInfo的proto格式:regionId,tableName,startKey,endKey,offline,split,replicaId;server格式:HRegionServer对应的server:port;serverstartcode格式是HRegionServer的启动时间戳。

HRegionServer详解

HRegionServer一般和DataNode在同一台机器上运行,实现数据的本地性。HRegionServer包含多个HRegion,由WAL(HLog)、BlockCache、MemStore、HFile组成。

WAL(Write Ahead Log, HLog)

所有写操作都会先保证将数据写入这个Log文件(每个HRegionServer只有一个)后,才会真正更新MemStore,最后写入HFile中。这样即使HRegionServer宕机,我们依然可以从HLog中恢复数据。

由于HDFS只允许同一时刻对一个文件只能一个客户端写入,所以对HLog只能单线程写入。这样很明显会影响性能,所以再***1.0以后的版本,多个WAL并行写(MultiWAL),该实现采用HDFS的多个管道写,以单个HRegion为单位。

BlockCache

读缓存,Hbase中有两种(BlockCache为HRegionServer内存大小的20%)

on-heap LruBlockCache:LruBlockCache受到java gc的影响,不稳定BucketCache(通常是off-heap):一般采用这种方式,自己管理内存,更加稳定

HRegion

HRegion是一个表的一部分,表的横切的一部分

HStore

HRegion由多个Store(HStore)构成,每个HStore对应了一个Table在这个HRegion中的一个Column Family,即每个Column Family就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。

HStore是***中存储的核心,它实现了读写HDFS功能,一个HStore由一个MemStore 和0个或多个HFile组成。

MemStore:所有数据的写在完成WAL日志写后,会 写入MemStore中,由MemStore根据一定的算法将数据Flush到地层HDFS文件中(HFile),通常每个HRegion中的每个 Column Family有一个自己的MemStore。HFile:在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列

MemStore

每一次Put/Delete请求都是先写入到MemStore中,当MemStore满后会Flush成一个新的StoreFile(底层实现是HFile),即一个HStore(Column Family)可以有0个或多个StoreFile(HFile)。有以下三种情况可以触发MemStore的Flush动作,需要注意的是MemStore的最小Flush单元是HRegion而不是单个MemStore。据说这是Column Family有个数限制的其中一个原因,估计是因为太多的Column Family一起Flush会引起性能问题

MemStore超过128M,此时当前的HRegion中所有的MemStore会Flush到HDFS中。HRegionServer上所有MemStore的大小超过了机器上默认40%的内存使用量。此时当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush顺序是MemStore大小的倒序,直到低于某个阈值,默认38%WAL过大,当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush使用时间顺序,最早的MemStore先Flush直到WAL的数量少于某个阈值。

在MemStore Flush过程中,还会在尾部追加一些meta数据,其中就包括Flush时最大的WAL sequence值,以告诉***这个StoreFile写入的最新数据的序列,那么在Recover时就直到从哪里开始。

HFile格式

v1

HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。

v2

v3

v3和v2没有太大变化,只是加了一个tag字段

理一理HRegionServer中的结构

HRegionServerWAL(Hlog,一个,HDFS中)BlockCacheHRegion(最多1000个,表的横切,rowkey不会重叠)HStore(列族,HRegion的列切, 多个)MemStore(写完Hlog后,刚生成的数据)HFile(多个,具体的数据,排序,HDFS中)

HRegionServer写流程

***读流程

***写时,相同Cell(RowKey/ColumnFamily/Column相同)并不保证在一起,甚至删除一个Cell也只是写入一个新的Cell,它含有Delete标记,而不一定将一个Cell真正删除了,因而这就引起了一个问题,如何实现读的问题?

相同的cell可能存在3个不同的位置,Block Cache,MemStore,HFile中。

从Block Cache中读取从MemStore中读取从多个HFile中读取,用Bloom Filter筛掉明显不存在所需数据的HFile,Index用于快速定位HFile中的数据块

Compaction

HFile过多,在数据读取的时候,会产生性能问题。所以一段时间后,HFile会进行合并。***中Compaction分为两种:Minor Compaction和Major Compaction。

HRegion Split

最初,一个Table只有一个HRegion,随着数据写入增加,如果一个HRegion到达一定的大小,就需要Split成两个HRegion,这个大小由hbase.hregion.max.filesize指定,默认为10GB。

分裂流程

RegionServer在本地决定分割HRegion,并准备分割。第一步,汇报给zookeeper。master获取zookeeper中的状态。RegionServer在HDFS的父目录区域目录下创建一个名为“.splits”的子目录。RegionServer关闭父HRegion,强制刷新缓存,并将该区域标记为本地数据结构中的脱机状态。此时,来到父区域的客户端请求将抛出NotServingRegionException异常。客户端将重试一些备用值。RegionServer在.splits目录下创建Region目录,为子区域A和B创建必要的数据结构。然后,它分割存储文件,因为它在父区域中为每个存储文件创建两个引用文件。那些引用文件将指向父Region文件。RegionServer在HDFS中创建实际的区域目录,并移动每个子Region的引用文件。RegionServer向META表发送请求。将父HRegion设置为.META中的脱机状态,并添加关于子HRegion的信息。在这时,在META中不会为女儿分配单独的条目。客户端会看到父区域是分割的,如果他们扫描.META,但不知道子HRegion,直到他们出现在.META。RegionServer并行open子HRegion接受写入。RegionServer将女儿A和B添加到.META。以及它所在地区的信息。此后,客户可以发现新的地区,并向新的地区发出请求,之前的缓存失效。HRegion Server向zookeeper汇报split结束的消息,master进行负载均衡。拆分后,meta表和HDFS仍将包含对父HRegion的引用。当子HRegion进行Compaction时,这些引用信息会被删除。Master也会定期检查子HRegion,如果没有父HRegion中的信息,父HRegion将被删除。

HRegion分裂后负载均衡

既然有拆分,但是HRegion也可以合并。HRegion调用closeAndMerge把两个HRegion合并(需要两个HRegion停止服务)

***中的负载均衡

负载均衡器会平衡系统中每个HRegionServer中HRegion个数。

负载均衡对系统性能影响很大,实际一般关闭,每周开启一次。

容错

HRegionServer Recovery

zookeeper感知,通知HMaster重新分配HRegion到其他节点为每个HRegion拆分WAL,将拆分出的WAL文件写入对应的目的HRegionServer的WAL目录中,并并写入对应的DataNode中回放WAL,重建MemStore

HMaster Recovery

依靠zookeeper进行主备切换

***一致性

***是强一致性,它表现在:

HRegion split时相关HRegion不可用HRegion合并时相关HRegion不可用HRegionServer Recovery时相关HRegion不可用

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一、TiDB分布式数据库培训实战教程(分布式集群架构、分布式大数据平台)视频教程
下一篇:面向列的分布式数据库Hbase简介
相关文章