深入HBase
1.HBase架构分析
- zookeeper:
1.为HBase集群提供协调服务;
2.管理HMaster和HRegionServer的状态;
3.在HRegionServer宕机时通知HMaster; - HMaster:
Hmaster为HBase集群的主节点,集群支持多个HMaster主节点(根据zookeeper选主),以此实现HA;
主要职责:
1 管理HRegionServer,实现负载均衡;
2 管理和分配Region;
3 管理namespace和Table的元数据(存储在HDFS上);
4 权限控制; - HRegionServer:
1.HBase集群的从节点;
2.HRegionServer一般建议和DataNode部署在同一台服务器上,以此减少数据的传输;
3.HRegionServer包含了一个HLog和多个HRegion,只要是对数据产生变化的操作都会先记录到HLog中,然后才把数据写入到对应的HRegion中,HRegion则是实际存储数据的地方; - 客户端请求流程:
1.客户端在连接hbase的时候首先需要连接到zookeeper;
2.首先会找zookeeper里面/hbase/meta-region-server节点,这个节点里面保存了meta表的数据,也就是region所在的regionserver信息;
3.客户端调用对应的reigonServer获取meta中存储的信息(meta中存储了hbase中所有表的相关信息),并在本地缓存当前需要用到的部分meta信息(因为meta信息在数据量多的时候是很大的,不可能缓存全部数据),以避免频繁调用regionServer获取meta信息;
2.Region概述
一张表中的数据,会按照行被横向划分为多个region(区域),每个region是按照存储的rowkey的最小行键和最大行键指定的【startRowKey,endRowKey】同时rowkey是有序存储的,同时随着表中的数据越来越多,region也会越来越大,当region大到一定程度的时候会自动拆分,以确保region始终不会太大;
一张表如果数据量很大的话会有多个region,region内部的每个列族都会是一个单独的文件;
总结:
一行数据如果有多个列族,则该行数据会被存储在多个文件中,同理,一个列族如果数据流量够大的话也会被存储在多个region中(横向切分);
一个region中可以包含多个列族文件;
3.Region详解
1.一个HRegion中包含多个Store(因为一个表可能会有多个列族),每个列族对应一个Store;
2.Store中包含两部分内容,MemStore(基于内存的Store)和StoreFile;
3.当有请求需要写数据的时候首先会写入MemStore,当MemStore达到阈值之后才会把数据持久化到StoreFile中;
4.StoreFile底层对应一个HFile文件,这个HFile文件最终会通过DFS Client写入到HDFS中;
4.HLog
WAL(Write-Ahead-Logging预写日志系统)最重要的作用是灾难恢复,作用类似于mysql的binlog,它记录所有对数据的变动操作,一旦服务器崩溃,通过重放log可以恢复崩溃之前的数据;
HLog是WAL的一个实现类,一个HRegionServer只有一个HLog,因为数据在Region中首先会被存在MemStore中,此时还没有持久化,当此时服务器宕机的时候,MemStore中的数据就会丢失,通过HLog的重放功能,则可以保证数据最终都会被持久化到HFile中,也就是被存储到HDFS中;
WAL的持久化等级分为如下四个等级:
SKIP_WAL:只写缓存,不写HLog日志。这种方式因为只写内存,因此可以极大的提升写入性能,但是数据有丢失的风险。在实际应用过程中并不建议设置此等级,除非确认不要求数据的可靠性。
ASYNC_WAL:异步将数据写入HLog日志中。
SYNC_WAL:同步将数据写入日志文件中,需要注意的是数据只是被写入文件系统中,并没有真正落盘,默认。
FSYNC_WAL:同步将数据写入日志文件并强制落盘。最严格的日志写入等级,可以保证数据不会丢失,但是性能相对比较差。
除了在创建表的时候直接设置WAL存储级别,也可以通过客户端设置WAL持久化等级。
5.HFile
HFile是HBase中最小的结构,HBase的底层数据都存放在HFile中,HFile从根本上说就是HDFS中的文件,只是它有自己特殊的格式;
HFile文件由六部分组成;
- Data:
以key-value的形式保存表中的数据,这部分数据可以被压缩,每个块都有一个Magic头,这个Magic头里面存储偏移量和第一个key; - Meta:
主要存储用户自定义的一些key-value,这部分是可选的; - File Info:
它是定长的,主要记录了文件的一些元数据信息; - Data Index:
记录了每个数据块的起始索引; - Meta Index:
记录了每个元数据块的起始索引; - Trailer:
它是定长的,主要用于指向其它数据块的一个起始点;
6.BloomFilter布隆过滤器
布隆过滤器是一种概率型数据结构,它能够准确判断该HFile中的所有数据块是否有我们需要查询的数据,从而大大减少不必要的块加载(采用该过滤器会在生成HFile的时候包含一份布隆过滤器结构的数据,开启布隆过滤器会有一定的存储及内存开销,大多数情况下这种负担对于带来的效果来说都是可以接受的),它是HBase中的高级功能,它能减少特定访问模式(get/scan)下的查询时间,提高HBase集群吞吐量;
7.HFile compaction(合并)机制
当MemStore达到阈值时会产生一个StoreFile(HFile)文件,随着数据量的持续写入,StoreFile文件会越来越多,最终导致读性能的下降,因此可以对这些StoreFile文件进行合并操作,将多个StoreFile文件合并成一个StoreFile文件,合并操作会对HBase的数据进行大量的IO操作;
合并操作分为major(大合并)和minor(小合并)两种;
minor(小合并): 只做部分文件的合并操作,合并过程一般比较快,而且IO相对较低;
major(大合并): 将Region下的所有HFile合并成一个文件(会忽略掉已经删除的文件,TTL过期的文件,版本超过限定的数据),会产生大量的IO操作,对HBase的读写性能造成较大影响(线上环境一般会关闭大合并功能,改为手动触发);
8.Region split(分裂)机制
HBase在创建表的时候默认只会分配一个region,为了达到负载均衡,当region达到一定大小时会将region分裂成2个新的子region,同时清除掉父region,HMaster会根据负载均衡策略,重新分配region所属的regionServer,从而发挥分布式系统的优点;
触发region split的条件:
ConstantSizeRegionSplitPolicy(0.94版本前默认切分策略),一个region中最大HFile的大小大于设置的阈值之后才会触发切分(对小表不友好);
IncreasingToUpperBoundRegionSplitPolicy(0.94~2.X版本默认切分策略),自动动态根据region数量以及在regionServer上的分布动态调整,最大大小也通过hbase.hregion.max.filesize这个参数来控制大小,使其在这个范围内动态调控;
9.Region LoadBalance策略
HMaster会根据指定的负载均衡策略挑选出一些region,并将这些region分配到负载比较低的regionServer上,由于HBase中的所有数据都是写到HDFS中的,因此HBase中region的移动其实是非常轻量级的(保持Region对应的HDFS文件位置不变,只需要将Region的元数据分配到对应的RegionServer上即可);
官方目前支持两种Region分配策略:
DefaultLoadBalancer:
这种策略保证每个RegionServer中的Region个数基本上都相等(假如有些region数量大,有些region数量小,在这种情况下其实是不均衡的);
StochasticLoadBalancer:
综合权衡的负载均衡策略,大致由每台服务器读请求数、每台服务器写请求数、Region个数、移动代价、数据Locality、每张表占据RegionServer中Region个数上线决定;