Hbase架构

 一、 Hbase基本架构

 

架构角色:

1)Region Server

Region Server为 Region的管理者,其实现类为HRegionServer,主要作用如下:
Regionserver维护region,处理对这些region的IO请求
Regionserver负责切分在运行过程中变得过大的region
对于数据的操作:get, put, delete;
对于Region的操作:splitRegion、compactRegion。

2)Master

Master是所有Region Server的管理者,其实现类为HMaster,主要作用如下:
实现DDL操作(Data Definition Language,namespace和table的增删改,column familiy的增删改等)。
对于RegionServer的操作:分配regions到每个RegionServer,监控每个RegionServer的状态,负载均衡和故障转移。
为Region server分配region
发现失效的Region server并重新分配其上的region
管理用户对table的增删改查操作

3)Zookeeper

HBase通过Zookeeper来做master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。
通过选举,保证任何时候,集群中只有一个master,Master与RegionServers 启动时会向ZooKeeper注册
存贮所有Region的寻址入口
实时监控Region server的上线和下线信息。并实时通知给Master
存储HBase的schema和table元数据
默认情况下,HBase 管理ZooKeeper 实例,比如, 启动或者停止ZooKeeper
Zookeeper的引入使得Master不再是单点故障

4)HDFS

HDFS为Hbase提供最终的底层数据存储服务,同时为HBase提供高可用的支持。

二、RegionServer 架构

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

1)StoreFile


每个Store会有一个或多个StoreFile(HFile),数据在每个StoreFile中都是有序的。
HFile(StoreFile) 用于存储HBase的数据(Cell/KeyValue)。StoreFile以Hfile的形式存储在HDFS上。
在HFile中的数据是按RowKey、Column Family、Column排序,
对相同的Cell(即这三个值都一样),则按timestamp倒序排列,数据在每个StoreFile中都是有序的。

2)MemStore

MemStore是一个写缓存(In Memory Sorted Buffer),所有数据的写在完成WAL日志写后,
由于HFile中的数据要求是有序的,排好序后,会先写入MemStore中,
由MemStore根据一定的算法将数据Flush到地层HDFS文件中(HFile),
每次刷写都会形成一个新的HFile。通常每个HRegion中的每个 Column Family有一个自己的MemStore。

3)WAL

WAL即Write Ahead Log,在早期版本中称为HLog,它是HDFS上的一个文件,如其名字所表示的,
所有写操作都会先保证将数据写入这个Log文件后,才会真正更新MemStore,最后写入HFile中。
采用这种模式,可以保证HRegionServer宕机后,我们依然可以从该Log文件中读取数据,
Replay所有的操作,而不至于数据丢失。这个Log文件会定期Roll出新的文件而删除旧的文件
(那些已持久化到HFile中的Log可以删除)。WAL文件存储在/hbase/WALs/${HRegionServer_Name}的目录中
(在0.94之前,存储在/hbase/.logs/目录中),一般一个HRegionServer只有一个WAL实例,
也就是说一个HRegionServer的所有WAL写都是串行的(就像log4j的日志写也是串行的),
这当然会引起性能问题,因而在HBase 1.0之后,通过HBASE-5699实现了多个WAL并行写(MultiWAL),
该实现采用HDFS的多个管道写,以单个HRegion为单位。关于WAL可以参考Wikipedia的Write-Ahead Logging。

4)BlockCache

BlockCache是一个读缓存,即“引用局部性”原理(也应用于CPU,分空间局部性和时间局部性,
空间局部性是指CPU在某一时刻需要某个数据,那么有很大的概率在一下时刻它需要的数据在其附近;
时间局部性是指某个数据在被访问过一次后,它有很大的概率在不久的将来会被再次的访问),
将数据预读取到内存中,以提升读的性能。HBase中提供两种BlockCache的实现:
默认on-heap LruBlockCache和BucketCache(通常是off-heap)。
通常BucketCache的性能要差于LruBlockCache,然而由于GC的影响,LruBlockCache的延迟会变的不稳定,
而BucketCache由于是自己管理BlockCache,而不需要GC,因而它的延迟通常比较稳定,这也是有些时候需要选用BucketCache的原因。

5)HRegion

HRegion是一个Table中的一个Region在一个HRegionServer中的表达。一个Table可以有一个或多个Region,
他们可以在一个相同的HRegionServer上,也可以分布在不同的HRegionServer上,一个HRegionServer可以有
多个HRegion,他们分别属于不同的Table。HRegion由多个Store(HStore)构成,每个HStore对应了一个Table
在这个HRegion中的一个Column Family,即每个Column Family就是一个集中的存储单元,因而最好将具有相
近IO特性的Column存储在一个Column Family,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。
HStore是HBase中存储的核心,它实现了读写HDFS功能,一个HStore由一个MemStore 和0个或多个StoreFile组成。

 

三、写流程

写流程:

1)Client先访问zookeeper,获取hbase:meta表位于哪个Region Server。

2)访问对应的Region Server,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。

3)与目标Region Server进行通讯;

4)将数据顺序写入(追加)到WAL(Flush到磁盘中);

5)将数据写入对应的MemStore,数据会在MemStore进行排序;

6)向客户端发送ack;

7)等达到MemStore的刷写时机后,将数据刷写到HFile。每次刷写都会生成一个新的hfile文件。

四、MemStore Flush

MemStore刷写时机:

1.当某个memstore的大小达到了hbase.hregion.memstore.flush.size(默认值128M,其所在region的所有memstore都会刷写。我们每次调用 put、delete 等操作都会检查的这个条件的。

当memstore的大小达到了

hbase.hregion.memstore.flush.size(默认值128M)

* hbase.hregion.memstore.block.multiplier(默认值4)=512M

时,会阻止继续往该memstore写数据。这时候如果你往对应的 Store 写数据,会出现 RegionTooBusyException 异常。

2.当region server中memstore的总大小达到

java_heapsize  (RegionServer 占用的堆内存大小)

*hbase.regionserver.global.memstore.size(默认值0.4)

*hbase.regionserver.global.memstore.size.lower.limit(默认值0.95),

region会按照其所有memstore的大小顺序(由大到小)依次进行刷写。直到region server中所有memstore的总大小减小到上述值以下。

HBase 为 RegionServer 的 MemStore 分配了一定的写缓存,大小等于 
hbase_heapsize(RegionServer 占用的堆内存大小)
* hbase.regionserver.global.memstore.size。
hbase.regionserver.global.memstore.size 的默认值是 0.4,
也就是说写缓存大概占用 RegionServer 整个 JVM 内存使用量的 40%。

当region server中memstore的总大小达到

java_heapsize

*hbase.regionserver.global.memstore.size(默认值0.4)

时,会阻止继续往所有的memstore写数据。

注意:0.99.0 之前 hbase.regionserver.global.memstore.size 是 hbase.regionserver.global.memstore.upperLimit 参数;

hbase.regionserver.global.memstore.size.lower.limit 是 hbase.regionserver.global.memstore.lowerLimit
RegionServer 级别的 Flush 策略是每次找到 RS 中占用内存最大的 Region 对他进行刷写,
这个操作是循环进行的,直到总体内存的占用低于全局 MemStore 刷写下
限(hbase.regionserver.global.memstore.size.lower.limit 
* hbase.regionserver.global.memstore.size * hbase_heapsize)才会停止。

需要注意的是,如果达到了 RegionServer 级别的 Flush,那么当前 RegionServer 的所有写操作将会被阻塞,
而且这个阻塞可能会持续到分钟级别。

3. 到达自动刷写的时间,也会触发memstore flush。自动刷新的时间间隔由该属性进行配置

hbase.regionserver.optionalcacheflushinterval(默认1小时)。

4.当WAL文件的数量超过hbase.regionserver.max.logs,region会按照时间顺序依次进行刷写,直到WAL文件数量减小到hbase.regionserver.max.log以下(该属性名已经废弃,现无需手动设置,最大值为32)。

在MemStore Flush过程中,还会在尾部追加一些meta数据,其中就包括Flush时最大的WAL sequence值,以告诉HBase这个StoreFile写入的最新数据的序列,那么在Recover时就知道从哪里开始。在HRegion启动时,这个sequence会被读取,并取最大的作为下一次更新时的起始sequence。

五、读流程

1)整体流程

2)Merge细节

读流程

1)Client先访问zookeeper,获取hbase:meta表位于哪个Region Server。

2)访问对应的Region Server,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。

3)与目标Region Server进行通讯;

4)分别在MemStore和Store File(HFile)中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete)。

5)将查询到的新的数据块(Block,HFile数据存储单元,默认大小为64KB)缓存到Block Cache。

6)将合并后的最终结果返回给客户端。

 

注意:Hbase的读写操作不需要Master的参与,元数据的操作必须有Master的参与,

六、StoreFile Compaction

由于memstore每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile。为了减少HFile的个数,以及清理掉过期和删除的数据,会进行StoreFile Compaction。

Compaction分为两种,分别是Minor CompactionMajor Compaction。Minor Compaction会将临近的若干个较小的HFile合并成一个较大的HFile,并不清理过期和删除的数据。Major Compaction会将一个Store下的所有的HFile合并成一个大HFile,并且清理掉所有过期和删除的数据

 一个region进行 major compaction合并的周期的参数是<hbase.hregion.major.compaction>,在这个点的时候,这个region下的所有hfile会进行合并,默认是7天,major compaction非常耗费资源,建议生产关闭(设置为0),在应用空闲的时候手动触发。图为官方配置文档。

 

 七、Region Split

默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的Region Server,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的Region Server。

Region Split时机:

1.当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize,该Region就会进行拆分(0.94版本之前)。

2.当1个region中的某个Store下所有StoreFile的总大小超过Min(initialSize*R^3 ,hbase.hregion.max.filesize"),该Region就会进行拆分。其中initialSize的默认值为2*hbase.hregion.memstore.flush.size,R为当前Region Server中属于该Table的Region个数(0.94版本之后)。

具体的切分策略为:

第一次split:1^3 * 256 = 256MB

第二次split:2^3 * 256 = 2048MB

第三次split:3^3 * 256 = 6912MB

第四次split:4^3 * 256 = 16384MB > 10GB,因此取较小的值10GB

后面每次split的size都是10GB了。

3.Hbase 2.0引入了新的split策略:如果当前RegionServer上该表只有一个Region,按照2 * hbase.hregion.memstore.flush.size分裂,否则按照hbase.hregion.max.filesize(默认10G)分裂。

4.关于分裂的思考

1. 第一次分裂很快,是因为我们希望表迅速扩展到所有regionserver上
2. 当1达到后,我们不希望继续快速分裂,是因为Hbase不宜有太多region

为什么region数量不宜过多:

1. Region数量多,RS内存压力更大;
2. Region过多,会频繁触发第二个flush时机,导致过多的小文件(storefile),从而频繁触发storefile合并
3. master对过多数量的Regions非常敏感(0.96版本Hbase已经改进)
4. 老版本Hbase会在内存中建立索引,region过多,索引过大,潜在OOM风险就上升了

Region分裂

1. 父Region下线,子Region建立父Region的StoreFile软连接,上线(此时子Region已经可以接受数据写入了)
2. 在MajorCompaction时候,对父Region的数据进行筛选删除,生成自己的完成的StoreFile
3. 父Region所有文件的软链接引用全部失效时,父Region的数据才会真正的删除

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值