《HBase原理与实践》阅读笔记(三)

学习笔记(7-8章)1.Compaction实现1.1.Compaction基本工作原理1.1.1.Compaction核心作用1.1.2.Compaction触发时机1.1.3.待合并HFile集合选择策略1.1.4.挑选合适的执行线程池1.1.5.Compaction BandWidth Limit两个重要参数2.Hbase负载均衡2.1.Region迁移2.2.Region合并2.3.Reg...
摘要由CSDN通过智能技术生成

本博客内容基本整理自《Hbase原理与实践》一书。仅用于个人学习和积累。

1.Compaction实现

Compaction是从一个Region的一个Store中选择部分HFile文件进行合并。合并原理是,先从这些待合并的数据文件中依次读出KeyValue,再由小到大排序后写入一个新的文件。之后,这个新生成的文件就会取代之前已合并的所有文件对外提供服务。

1.1.Compaction基本工作原理

HBase根据合并规模将Compaction分为两类:Minor CompactionMajor Compaction

  • Minor Compaction是指选取部分小的、相邻的HFile,将它们合并成一个更大的HFile。
  • Major Compaction是指将一个Store中所有的HFile合并成一个HFile,这个过程还会完全清理三类无意义数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据
1.1.1.Compaction核心作用
  • 合并小文件,减少文件数,稳定随机读延迟。
  • 提高数据的本地化率。
  • 清除无效数据,减少数据存储量。
1.1.2.Compaction触发时机

HBase中触发Compaction的时机主要有如下三种:MemStore Flush、后台线程周期性检查以及手动触发。
Compaction操作的源头来自flush操作。

1.1.3.待合并HFile集合选择策略

选择合适的文件进行合并是整个Compaction的核心。在HBase早期的版本中,分别提出了两种选择策略:RatioBasedCompactionPolicy以及ExploringCompactionPolicy,这些策略首先对该Store中所有HFile逐一进行排查,排除不满足条件的部分文件,经过排除后留下来的文件称为候选文件,接下来HBase再判断侯选文件是否满足Major Compaction条件,如果满足,就会选择全部文件进行合并,如果不满足Major Compaction条件,就必然为Minor Compaction。具体条件详见书本内容。

1.1.4.挑选合适的执行线程池

Compaction触发后经过选择策略挑选出合适的文件后,就需要选择合适的线程池去执行Compaction操作。
HBase实现中有一个专门的类CompactSplitThead负责接收Compaction请求和split请求,而且为了能够独立处理这些请求,这个类内部构造了多个线程池:largeCompactions、smallCompactions以及splits等。splits线程池负责处理所有的split请求,largeCompactions用来处理大Compaction,smallCompaction负责处理小Compaction。
注:大Compaction并不是Major Compaction,小Compaction也并不是Minor Compaction。HBase定义了一个阈值hbase.regionserver.thread.compaction.throttle,如果Compaction合并的总文件大小超过这个阈值就认为是大Compaction,否则是小Compaction。

1.1.5.Compaction BandWidth Limit两个重要参数
  • compactBwLimit :一次Compaction的最大带宽使用量,如果Compaction所使用的带宽高于该值,就会强制其sleep一段时间。
  • numOfFilesDisableCompactLimit :在写请求非常大的情况下,限制Compaction带宽的使用量必然会导致HFile堆积,进而会影响读请求响应延时。因此该值意义很明显,一旦Store中HFile数量超过该设定值,带宽限制就会失效。

2.Hbase负载均衡

负载均衡是分布式集群设计的一个重要功能,只有实现了负载均衡,集群的可扩展性才能得到有效保证。数据库集群负载均衡的实现依赖于数据库的数据分片设计,可以在一定程度上认为数据分片就是数据读写负载,那么负载均衡功能就是数据分片在集群中均衡的实现。HBase中数据分片的概念是Region。

2.1.Region迁移

Hbase的负载均衡中Region迁移是一个轻量级操作,因为Hbase的实际数据实际存储在HDFS上,并不需要独立管理。但其实现逻辑依然比较复杂。复杂性主要表现在两个方面:其一,Region迁移过程涉及多种状态的改变;其二,迁移过程中涉及Master、ZooKeeper(ZK)以及RegionServer等多个组件的相互协调。
下图为Hbase中定义的Region迁移时会存在的几种状态:
在这里插入图片描述
在实际执行过程中,Region迁移操作其实就分两个阶段:unassign阶段和assign阶段。即Region从源RegionServer的上下线和下线。
Region的这些状态会存储在三个区域:

  • meta表。meta表只存储Region所在的RegionServer,并不存储迁移过程中的中间状态。
  • Master内存。Master内存中存储整个集群所有的Region信息,根据这个信息可以得出此Region当前以什么状态在哪个RegionServer上。我们在HBase Master WebUI上看到的Region状态都来自于Master内存信息。注:由于Master存储的Region状态变更都是由RegionServer通过ZooKeeper通知给Master的,所以Master上的Region状态变更总是滞后于真正的Region状态变更。
  • ZooKeeper的region-in-transition节点。ZooKeeper中存储的是临时性的状态转移信息,作为Master和RegionServer之间反馈Region状态的通道。

2.2.Region合并

从原理上看,Region合并的主要流程如下:
1)客户端发送merge请求给Master。
2)Master将待合并的所有Region都move到同一个RegionServer上。
3)Master发送merge请求给该RegionServer。
4)RegionServer启动一个本地事务执行merge操作。
5)merge操作将待合并的两个Region下线,并将两个Region的文件进行合并。
6)将这两个Region从hbase:meta中删除,并将新生成的Region添加到hbase:meta中。
7)将新生成的Region上线。
HBase使用merge_region命令执行Region合并,如下:

$ hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME'
$ hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME', true #带上参数true可以强制让不相邻的Region进行合并,否则只能合并相邻Region。风险较大,一般不建议生产环境使用。

2.3.Region分裂

Region分裂是HBase最核心的功能之一,是实现分布式可扩展性的基础。
2.0版本默认分裂策略为SteppingSplitPolicy

2.3.1.寻找分裂点

满足分裂策略之后就会触发Region分裂。而分裂的首要任务就是寻找分裂点。
HBase对于分裂点的定义为:整个Region中最大Store中的最大文件中最中心的一个Block的首个rowkey。注,当待分裂Region只有一个Block,即如果定位到的rowkey是整个文件的首个rowkey或者最后一个rowkey,则认为没有分裂点。

2.3.2.分裂流程

整个分裂事务过程分为三个阶段:prepare、execute和rollback。
该部分书中讲解十分详细,其中我个人认为的重点是在execute阶段会新建临时文件夹.split并在其下新建两个子文件夹,称为daughter A、daughter B,并在文件夹中生成reference文件,分别指向父Region中对应文件。

2.3.2.1.reference文件介绍

reference文件是一个引用文件(并非Linux链接文件),
通过reference文件名就可以知道reference文件指向哪个父Region中的哪个HFile文件。同时reference文件的文件内容也非常重要。其文件内容并不是用户数据,而是由两部分构成:其一是分裂点splitkey,其二是一个boolean类型的变量(true或者false),true表示该reference文件引用的是父文件的上半部分(top),false表示引用的是下半部分(bottom)。用户可以使用hadoop命令查看reference文件的具体内容:

hadoop dfs -cat /hbase-rsgroup/data/default/music/0155388346c3c919d3f05d7188e885e0/cf/d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66
2.3.2.2.父Region被删除的时间

父Region经过分裂流程分裂为两个子Region后通知修改hbase:meta表后下线,不再提供服务。下线后父Region在meta表中的信息并不会马上删除,而是将split列、offline列标注为true,用于之后的删除做判断。
Master会启动一个线程定期遍历检查所有处于splitting状态的父Region,确定父Region是否可以被清理。检查过程分为两步:
1)检测线程首先会在meta表中读出所有split列为true的Region,并加载出其分裂后生成的两个子Region(meta表中splitA列和splitB列)。
2)检查两个子Region是否还存在引用文件,如果都不存在引用文件就可以认为该父Region对应的文件可以被删除。

2.4.负载均衡应用

在实际生产线环境中,负载均衡机制最重要的一个应用场景是系统扩容。扩容操作一般分为两个步骤:首先,需要增加节点并让系统感知到节点加入;其次,需要将系统中已有节点负载迁移到新加入节点上。第二步负载迁移在具体实现上需要借助于负载均衡机制。

StochasticLoadBalancer是目前HBase默认的负载均衡策略。相比SimpleLoadBalancer策略而言它对于负载的定义不再是Region个数这么简单,而是由多种独立负载加权计算的复合值。
这些独立负载包括:

  • Region个数(RegionCountSkewCostFunction)
  • Region负载
  • 读请求数(ReadRequestCostFunction)
  • 写请求数(WriteRequestCostFunction)
  • Storefile大小(StoreFileCostFunction)
  • MemStore大小(MemStoreSizeCostFunction)
  • 数据本地率(LocalityCostFunction)
  • 移动代价(MoveCostFunction)

这些独立负载经过加权计算会得到一个代价值,系统使用这个代价值来评估当前Region分布是否均衡,越均衡代价值越低。HBase通过不断随机挑选迭代来找到一组Region迁移计划,使得代价值最小。

3.总结

通过今天的阅读,我了解到了Hbase是如何通过Compaction去实现将小文件合并成大文件,从而提高Hbase的读取效率。书中7.2节还介绍了Compaction的一些高级策略,那部分对于目前的我来说过于晦涩,因此笔记中也没有进行整理,留于之后深入学习。第8章介绍了HBase中Region的迁移、合并以及分裂等操作是如何实现的。其中,Region的分裂在工作环境中是经常碰到的,也时常在分裂过程中,也就是书中所说的负载均衡的过程中遇到问题。通过第八章的阅读,让我对这部分的流程有了更深的理解,特别是书中提到的reference文件,还有在分裂时Region存在的各种状态,这些信息对于问题的定位分析相信会有一定的帮助。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值