HBase 工作机制及读写流程

HBase

一图看懂 HBase 架构

HBase 最常用的shell操作

HBase 工作机制及读写流程



前言

本篇博客,为大家梳理 HBase 工作机制及读写流程。HBase 工作机制涉及 Master 工作机制和RegionServer 工作机制;读写流程涉及Region split分裂机制和compact 合并机制。过程难免枯燥乏味,但结果却很充实。


HBase 工作机制

HBase 工作机制涉及 Master 工作机制和RegionServer 工作机制。

Master工作机制

Master 的工作机制也分为上线和下线两种。

Master 上线

HBase集群中可以设置多个Hmaster,真正对外提供服务的只有一个。这是HBase集群 Master 上线 的前提条件。

HBase 高可用集群多个Hmaster设置步骤如下:

  • 关闭 hbase: stop-hbase.sh
  • 在conf目录下创建backup-masters文件:写入本机的hostname
  • 将backup-masters文件拷贝至其他节点同目录
  • 不要在非主机上启动hbase: start-hbase.sh

配置成功结果如下:
在这里插入图片描述

Master启动进行以下步骤:

  1. 从zookeeper上获取唯一 一个首先获得 active master的排他锁,用来阻止其它master成为真正的Master。

  2. 扫描zookeeper上的/hbase/rs节点,通过zookeeper集群协调监督的特性(主要通过心跳包机制)获得当前可用的region server列表。

  3. Master和每个region server通信,获得当前已分配的region和region server的对应关系。

  4. Master扫描META表,计算得到当前还未分配的region,将他们放入待分配region列表。

从 Master 的上线过程可以看到,Master 保存的信息全是可以冗余的信息(都可以从系统其它地方(WAL)收集或者计算得到)。因此,一般 HBase 集群中总是有一个 Master 在提供服务,还有一个以上的 Master 在等待时机抢占它的位置。

Master下线

master只维护表和region的元数据,不参与表数据IO的过程,所以master下线短时间内对整个hbase集群几乎没有影响。表的数据读写还可以正常进行。

Hmaster下线后的影响有无法创建删除表,无法修改表的schema,无法进行region的负载均衡,无法处理region 上下线,无法进行region的合并(region的split可以正常进行,它只有 RegionServer 参与)。

当Master下线后,启动Zookeeper的选举机制,选出新的Master,新的Master上线,执行上线流程。

RegionServer 工作机制

RegionServer 工作机制的前提条件是 Master 使用 ZooKeeper集群 来跟踪 RegionServer 状态。

Region 管理

任何时刻,一个Region只能分配给一个RegionServer。具体如下:

  • Master记录了当前有哪些可用的RegionServer。以及当前哪些Region分配给了哪些RegionServer,哪些Region还没有分配。
  • 当需要分配的新的Region,并且有一个RegionServer上有可用空间时,Master就给这个RegionServer发送一个装载请求,把Region分配给这个RegionServer。
  • RegionServer得到请求后,就开始对此Region提供服务。

region server上线

当某个 RegionServer 启动时,会首先在 ZooKeeper 上的 server 目录下创建一个代表自己的临时 ZNode,相当于抢占了server文件的独占锁。由于 Master 订阅了 server 目录下的变更消息(Watcher),当 server 目录下的文件出现新增或删除操作时,Master 可以得到来自 ZooKeeper 的实时通知,并将实时信息和操作记录到HLog文件中。因此一旦 RegionServer 上线,Master 就能马上得到消息。

region server下线

当 RegionServer 下线时,它和 ZooKeeper 的会话就会断开,ZooKeeper 会自动删除代表这台 RegionServer 的 ZNode,意味着该台 RegionServer 自动释放了 server 文件的独占锁(ZNode),也就是说Master 就可以确定这台 RegionServer 节点挂了。

无论出现哪种情况,RegionServer 都无法继续为它的 Region 提供服务了,此时,ZooKeeper 会将该台节点的变化信息反馈给Master,Master收到反馈, 就会将这台 RegionServer 上的未完成的 Region 任务分配给其它还活着的 RegionServer。

HBase 读写流程

HBase 读流程

HBase meta表

meta表存储了所有用户HRegion的位置信息,meta表内记录一行数据是用户表一个region的start key 到endkey的范围。meta表存储在一个zookeeper 知道的一个regionserver里。

HBase meta表 是HBase 读流程 寻址的关键所在。具体步骤如下图所示:

在这里插入图片描述

如上图HBase meta 寻址的过程一致,HBase 读流程具体步骤如下:

  1. 客户端通过 ZooKeeper 以及META表找到目标数据所在的 RegionServer(就是数据所在的 RegionServer 的主机地址);

  2. 客户端发生查询请求:联系 RegionServer 查询目标数据,然后 RegionServer 定位到目标数据所在的 Region,将信息反馈给RegionServer ;

  3. 客户端直接读取装载目标数据的 RegionServer读取 Region的结果数据。

此外, RegionServer 查询目标数据,会因为相同的cell(RowKey/ColumnFamily/Column相同)可能存在3个不同的位置,即Block Cache,MemStore,HFile中读取目标数据。具体如下图所示:

在这里插入图片描述
总结如下:

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

HBase 写流程

Client先访问zookeeper,找到Meta表,并获取Meta表元数据。确定当前将要写入的数据所对应的HRegion和HRegionServer服务器。Client向该HRegionServer服务器发起Put写入数据请求,在HRegionServer中它首先会将该Put操作写入WAL日志文件中,以防止数据丢失。

在这里插入图片描述

当写完WAL日志文件后,HRegionServer根据Put中的TableName和RowKey找到对应的HRegion,并根据Column Family找到对应的HStore,并将Put写入到该HStore的MemStore中。写入成功,返回给客户端。
在这里插入图片描述
当Memstore达到阈值,会把Memstore中的数据flush到Storefile中。

当Storefile越来越多,达到一定数量时,会触发Compact合并操作,将多个小文件合并成一个大文件。Storefile越来越大,Region也会越来越大,达到阈值后,会触发Split操作,变成两个文件。

flush 机制

HBase flush 机制涉及以下6大点:

  1. hbase.regionserver.global.memstore.size: 默认堆大小的40%
    regionServer的全局memstore的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%,而且regionserver级别的flush会阻塞客户端读写

  2. hbase.hregion.memstore.flush.size:默认128M
    单个region里memstore的缓存大小,超过那么整个HRegion就会flush。

  3. hbase.regionserver.optionalcacheflushinterval:默认1h
    内存中的文件在自动刷新之前能够存活的最长时间

  4. hbase.regionserver.global.memstore.size.lower.limit :默认堆大小 * 0.4 * 0.95
    有时候集群的“写负载”非常高,写入量一直超过flush的量,这时,我们就希望memstore不要超过一定的安全设置。在这种情况下,写操作就要被阻塞一直到memstore恢复到一个“可管理”的大小,这个大小就是默认值是堆大小 * 0.4 * 0.95,也就是当regionserver级别的flush操作发送后,会阻塞客户端写,一直阻塞到整个regionserver级别的memstore的大小为 堆大小 * 0.4 *0.95为止

  5. hbase.hregion.preclose.flush.size:默认为5M
    当一个 region 中的 memstore 的大小大于这个值的时候,我们就触发 了 close,会先运行“pre-flush”操作,清理这个需要关闭的memstore,然后 将这个 region 下线。当一个 region 下线了,我们无法再进行任何写操作。 如果一个 memstore 很大的时候,flush 操作会消耗很多时间。“pre-flush” 操作意味着在 region 下线之前,会先把 memstore 清空。这样在最终执行 close 操作的时候,flush 操作会很快。

  6. hbase.hstore.compactionThreshold:默认超过3个
    一个store里面允许存的hfile的个数,超过这个个数会被写到新的一个hfile里面 ,也即是每个region的每个列族对应的memstore在fulsh为hfile的时候,默认情况下当超过3个hfile的时候就会 对这些文件进行合并重写为一个新文件,设置个数越大可以减少触发合并的时间,但是每次合并的时间就会越长。

HBase flush 机制过程如下:

在这里插入图片描述

Compact合并操作

StoreFile 是只读的,一旦创建后就不可以再修改。因此 HBase 的更新/修改其实是不断追加的操作。

HBase 只是增加数据,所有的更新和删除操作,都是在 Compact 阶段做。所以,用户写操作只需要进入到内存即可立即返回,从而保证 I/O 的高性能。HBase中Compact分为两种:Minor Compact和Major Compact。

在这里插入图片描述

  • Minor Compact:是指选取一些小的、相邻的HFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。(BigTable中将memtable的数据flush的一个HFile/SSTable称为一次Minor Compaction)

  • Major Compact:是指将所有的HFile合并成一个HFile,可以手动触发或者自动触发,但是会引起性能问题,一般安排在周末。

Region Split操作

Client 写入数据 --> 存入 MemStore,一直到 MemStore 写满 --> Flush 成一个 StoreFile,直至增长到一定阈值 --> 触发 Compact 合并操作 --> 多个 StoreFile 合并成一个 StoreFile,同时进行版本合并和数据删除 --> 当 StoreFile 经过 Compact 之后,逐步形成越来越大的 StoreFile --> 单个 StoreFile 大小超过一定阈值后,触发 Split 操作,把当前 Region Split 成 2 个 Region,原来的 Region 会下线,新 Split 出来的 2 个子 Region 会被 HMaster 分配到相应的 RegionServer 上,使得原先的一个 Region 的压力被分流到 2 个 Region 上。

Region Split操作中是怎么样把 Region Split 成 2 个 Region的?什么情况下开始分裂,分裂有哪些方式,可以修改分裂配置吗?下面我将详细的介绍这些问题。

Region Split 流程

借鉴HBase:分布式列式NoSQL数据库的Region Split 流程说到非常好,这里我直接引用介绍如下:

在这里插入图片描述

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

Region Split的大小上限统一配置有以下两种方法进行更改默认配置项

  1. 通过修改全局配置文件hbase.hregion.max.filesizehbase.hregion.memstore.flush.size

    <property>
    	<name>hbase.hregion.max.filesize</name>
    	<value>10 *1024* 1024 * 1024</value>		# 默认为10G
    </property>
    <property>
    	<name>hbase.hregion.memstore.flush.size</name>
    	<value>128</value>							# 默认为128M
    </property>
    
  2. 单独设置

    # 第一步 禁用 TABLE_NAME
    disable 'TABLE_NAME'
    
    # 第二步	单独设置TABLE_NAME最大文件MAX_FILESIZE
    alter 'TABLE_NAME',METHOD => 'table_att',MAX_FILESIZE=>'134217728'
    
    # 第三步,启用 TABLE_NAME
    enable'TABLE_NAME'
    

Region Split 策略有以下四种方法

1. 最简单粗暴的策略ConstantsizeRegionSplitPolicy

就是Hbase默认的拆分。

2. 限制不断增长的文件尺寸分裂策略IncreasingToUpperBoundRegionSplitPolicy

说明:

  • 这是HBase 0.94.0 默认regionsplit策略

  • 根据根据公式Math.min(r^2*flushSize,maxFileSize)确定split的maxFilesize;这里假设flushsize为128M。拆分过程如下:

    第一次拆分大小为: min(10G,l*1*128M)=128M
    第二次拆分大小为: min(10G,3*3*128M)=1152M
    第三次拆分大小为: min(10G,5*5*128M)=3200M
    第四次拆分大小为: min(10G,7*7*128M)=6272M
    第五次拆分大小为: min(10G,9*9*128M)=10G
    
  • 两种split 拆分方式

    1. 同键(以定义的分隔符左侧作为是否同键认定)进同区DelimitedKeyPrefixRegionsplitPolicy.delimiter,比如"-"为分隔符进行分区
    2. 同键(截取从左向右固定长度的RowKey)进同区KeyPrefixRegionSplitPolicy.prefix_length,默认指定长度为16

3. 热点Region Split分裂策略BusyRegionSplitPolicy

说明:

  • 热点 Region 分裂策略:为被高频访问的 Region 设计的 Region Split分裂策略

  • 请求阻塞率:未达到该阻塞率不分裂,默认为20%

    <property>
    	<name>hbase.busy.policy.blockedRequests</name>
    	<value>0.2</value>
    </property>
    
  • 最小年龄10分钟:少于该时间不分裂,默认10分钟

    <property>
    	<name>hbase.busy.policy.minAge</name>
    	<value>600000</value>
    </property>
    
  • 计算是否繁忙的窗口:每隔多久统计一次:默认5分钟

    <property>
    	<name>hbase.busy.policy.aggWindow</name>
    	<value>300000</value>
    </property>
    
    1. 统计前提:当前时间-上次统计时间 >= hbase.busy.policy.aggWindow
    2. 计算公式:被阻塞访问次数/总访问次数 > hbase.busy.policy.blockedRequests
    3. 以上1和2条件成立:当前Region为Busy
    4. 注意:经常出现繁忙Region可以采用,但不确定因素会存在

4. 关闭/启用自动分裂DisabledRegionSplitPolicy

  • 预分裂:建表时定义自动拆分

    # 语法:
    hbase org.apache.hadoop.hbase.util.RegionSplitter test_split_table HexStringSplit -c 3 -f test_col
    
    # 说明:
    test_split_table		表名
    HexStringSplit			拆分点算法
    -c						分区数量
    -f						列族名称
    

    例如:

    hbase(main):011:0> scan 'hbase:meta',{STARTROW=>'productinfo',LIMIT=>10}
    

    结果:

    在这里插入图片描述

  • 预分裂:建表时定义手动拆分

    create 'test_split2','mycf2',SPLITS=>['aaaa','bbbb','cccc','dddd','eeee','fff']
    

    结果:
    在这里插入图片描述

  • 强制分裂:

    split	强制分裂方法的调用方式:
    split 'tableName'
    split 'namespace:tableName'
    split 'regionName' # format:'tableName,startKey,id'
    split 'tableName','splitKey'
    split 'regionName','splitKey'
    

    例如:

    hbase (main) :015:0>split 'student', 'b'
    

    结果:

    在这里插入图片描述

推荐方案

(1)用预拆分导入初始数据。

(2)然后用自动拆分来让HBase来自动管理Region

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值