HBase有很多话题可以聊,包括读写路径上涉及到的一些资料结构,效能优化以及优化读写做的一些设计等。今天要探讨的Compaction机制就是HBase架构上做的一个重要优化,其实关于HBase的架构设计、Flush&Compaction等文章已经多不胜数了,本文也是主要参考HBase官网、社群的一些文章总结,从各个关键点进行总结,旨在为了帮助我们更加牢固的掌握Compaction机制。
为什么要执行 Compaction
熟悉HBase的同学应该知道,HBase是基于一种LSM-Tree(Log-Structured Merge Tree)储存模型设计的,写入路径上是先写入WAL(Write-Ahead-Log)即预写日志,再写入memstore快取,满足一定条件后执行flush操作将快取资料刷写到磁盘,生成一个HFile资料档案。随着资料不断写入,磁盘HFile档案就会越来越多,档案太多会影响HBase查询效能,主要体现在查询资料的io次数增加。为了优化查询效能,HBase会合并小的HFile以减少档案数量,这种合并HFile的操作称为Compaction,这也是为什么要进行Compaction的原因。Compaction 作用
其实Compaction操作属于资源密集型操作特别是IO密集型,这点后面也会提及到,Compaction本质上其实就是牺牲了部分IO,以换取相对稳定的读取效能。Compaction 分类
HBase Compaction分为两种:Minor Compaction 与 Major Compaction,通常我们简称为小合并、大合并。下面是一个简单示意图
这里有个习惯是在讲述Compaction操作时我们有时以StoreFile来表述HFile,StoreFile底层就是HFile,可以理解为是HFile的一种轻量级封装。
Minor Compaction:指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次 Minor Compaction 的结果是更少并且更大的StoreFile。
Major Compaction:指将所有的StoreFile合并成一个StoreFile,这个过程会清理三类没有意义的资料:被删除的资料、TTL过期资料、版本号超过设定版本号的资料。另外,一般情况下,major compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此线上业务都会将关闭自动触发major compaction功能,改为手动在业务低峰期触发。
这里值得关注的一点是只有在触发执行major compaction后才会真正删除资料,包含写入的Delete资料、设定TTL的列族中已经过期的资料以及版本号过大的资料。
Compaction 触发条件
HBase触发Compaction的条件有三种:memstore Flush、后台执行绪周期性检查、手动触发。memstore flush:可以说compaction的根源就在于flush,memstore 达到一定阈值或其他条件时就会触发flush刷写到磁盘生成HFile档案,正是因为HFile档案越来越多才需要compact。HBase每次flush之后,都会判断是否要进行compaction,一旦满足minor compaction或major compaction的条件便会触发执行。
后台执行绪周期性检查: 后台执行绪 CompactionChecker 会定期检查是否需要执行compaction,检查周期为hbase.server.thread.wakefrequency * hbase.server.compactchecker.interval.multiplier,这里主要考虑的是一段时间内没有写入请求仍然需要做compact检查。其中引数 hbase.server.thread.wakefrequency 预设值 10000 即 10s,是HBase服务端执行绪唤醒时间间隔,用于log roller、memstore flusher等操作周期性检查;引数 hbase.server.compactchecker.interval.multiplier 预设值1000,是compaction操作周期性检查乘数因子。10 * 1000 s 时间上约等于2hrs, 46mins, 40sec。
手动触发:是指通过HBase Shell、Master UI界面或者HBase API等任一种方式 执行 compact、major_compact等命令。
Compaction 引数解析
Major Compaction 引数Major Compaction涉及的引数比较少,主要有大合并时间间隔与一个抖动引数因子,如下:
1.hbase.hregion.majorcompaction
Major compaction周期性时间间隔,预设值604800000,单位ms。表示major compaction预设7天排程一次,HBase 0.96.x及之前预设为1天排程一次。设定为 0 时表示禁用自动触发major compaction。需要强调的是一般major compaction持续时间较长、系统资源消耗较大,对上层业务也有比较大的影响,一般生产环境下为了避免影响读写请求,会禁用自动触发major compaction。
2.hbase.hregion.majorcompaction.jitter
Major compaction抖动引数,预设值0.5。这个引数是为了避免major compaction同时在各个regionserver上同时发生,避免此操作给丛集带来很大压力。 这样节点major compaction就会在 + 或 - 两者乘积的时间范围内随机发生。
Minor Compaction 引数
Minor compaction涉及的引数比major compaction要多,各个引数的目标是为了选择合适的StoreFile,具体引数如下:
1.hbase.hstore.compaction.min
一次minor compaction最少合并的StoreFile数量,预设值 3。表示至少有3个符合条件的StoreFile,minor compaction才会启动。一般情况下不建议调整该引数。
如果要调整,不建议调小该引数,这样会带来更频繁的压缩,调大该引数的同时其他相关引数也应该做调整。早期引数名称为 hbase.hstore.compactionthreshold。
2.hbase.hstore.compaction.max
一次minor compaction最多合并的StoreFile数量,预设值 10。这个引数也是控制着一次压缩的时间。一般情况下不建议调整该引数。调大该值意味着一次compaction将会合并更多的StoreFile,压缩时间将会延长。
3.hbase.hstore.compaction.min.size
档案大小
但是,在write-heavy就是写压力非常大的场景,可能需要微调该引数、减小引数值,假如每次memstore大小达到1~2M时就会flush生成StoreFile,此时生成的每个StoreFile都会加入压缩伫列,而且压缩生成的StoreFile仍然可能小于该配置值会再次加入压缩伫列,这样将会导致压缩伫列持续很长。
4.hbase.hstore.compaction.max.size
档案大小 > 该引数值的StoreFile将会被排除,不会加入minor compaction,预设值Long.MAX_VALUE,表示没有什么限制。一般情况下也不建议调整该引数。
5.hbase.hstore.compaction.ratio
这个ratio引数的作用是判断档案大小 > hbase.hstore.compaction.min.size的StoreFile是否也是适合进行minor compaction的,预设值1.2。更大的值将压缩产生更大的StoreFile,建议取值范围在1.0~1.4之间。大多数场景下也不建议调整该引数。
6.hbase.hstore.compaction.ratio.offpeak
此引数与compaction ratio引数含义相同,是在原有档案选择策略基础上增加了一个非高峰期的ratio控制,预设值5.0。这个引数受另外两个引数 hbase.offpeak.start.hour 与 hbase.offpeak.end.hour 控制,这两个引数值为[0, 23]的整数,用于定义非高峰期时间段,预设值均为-1表示禁用非高峰期ratio设定。
Compaction 执行绪池选择
HBase RegionServer内部专门有一个 CompactSplitThead 用于维护执行minor compaction、major compaction、split、merge操作的执行绪池。其中与compaction操作有关的执行绪池称为 largeCompactions(又称longCompactions) 与 smallCompactions(又称shortCompactions),前者用来处理大规模compaction,后者处理小规模compaction,执行绪池大小都预设为 1 即只分别提供了一个执行绪用于相应的compaction。
这里并不是major compaction就一定会交给largeCompactions执行绪池处理。关于HBase compaction分配给largeCompactions还是smallCompactions执行绪池受引数hbase.regionserver.thread.compaction.throttle控制,该引数预设值为2 * hbase.hstore.compaction.max * hbase.hregion.memstore.flush.size,如果flush size 大小是128M,该引数预设值就是2684354560 即2.5G。一次compaction的档案总大小如果超过该配置,就会分配给largeCompactions处理,否则分配给smallCompactions处理。
largeCompactions与smallCompactions的执行绪池大小可通过引数 hbase.regionserver.thread.compaction.large、hbase.regionserver.thread.compaction.small进行配置。对于compaction压力比较大的场景,如果要调大两种执行绪池的大小,建议调整范围在2~5之间,不建议设定过大否则可能会消费过多的服务端资源造成不良影响。
Compaction 策略介绍
HBase的compaction policy准确的说有4种,分别是RatioBasedCompactionPolicy、ExploringCompactionPolicy、FIFOCompactionPolicy 以及 StripeCompactionPolicy。其中,HBase使用的压缩策略主要就是前两种,HBase 0.96.x版本之前,预设的压缩策略是RatioBasedCompactionPolicy,HBase 0.96.x以及更新版本中,预设为ExploringCompactionPolicy。ExploringCompactionPoliy要比旧版本中的RatioBasedCompactionPolicy 效能更高,因此一般情况下也不建议改变预设配置。各种压缩策略之间更详细的区别不再介绍。如果在HBase 0.96.x之后仍想配置RatioBasedCompactionPolicy策略,可以通过修改hbase-site.xml新增hbase.hstore.defaultengine.compactionpolicy.class配置项,配置值为RatioBasedCompactionPolicy,恢复预设配置只需移除该配置项即可。
Compaction 对读写请求的影响
储存上的写入放大HBase Compaction会带来写入放大,特别是在写多读少的场景下,写入放大就会比较明显,下图简单示意了写入放大的效果。

随着minor compaction以及major Compaction的发生,可以看到,这条资料被反复读取/写入了多次,这是导致写放大的一个关键原因,这里的写放大,涉及到网络IO与磁盘IO,因为资料在HDFS中预设有三个副本。
读路径上的延时毛刺
HBase执行compaction操作结果会使档案数基本稳定,进而IO Seek次数相对稳定,延迟就会稳定在一定范围。然而,compaction操作会带来很大的带宽压力以及短时间IO压力。因此compaction就是使用短时间的IO消耗以及带宽消耗换取后续查询的低延迟。这种短时间的压力就会造成读请求在延时上会有比较大的毛刺。下图是一张示意图,可见读请求延时有很大毛刺,但是总体趋势基本稳定。

写请求上的短暂阻塞
Compaction对写请求也会有比较大的影响。主要体现在HFile比较多的场景下,HBase会限制写请求的速度。如果底层HFile数量超过hbase.hstore.blockingStoreFiles 配置值,预设10,flush操作将会受到阻塞,阻塞时间为hbase.hstore.blockingWaitTime,预设90000,即1.5分钟,在这段时间内,如果compaction操作使得HFile下降到blockingStoreFiles配置值,则停止阻塞。另外阻塞超过时间后,也会恢复执行flush操作。这样做可以有效地控制大量写请求的速度,但同时这也是影响写请求速度的主要原因之一。
Compaction 总结
HBase Compaction操作是为了资料读取做的优化,总的来说是以牺牲磁盘io来换取读效能的基本稳定。Compaction操作分为minor compaction与major compaction,其中major compaction消耗资源较大、对读写请求有一定影响,因此一般是禁用自动周期性执行而选择业务低峰期时手动执行。另外本文也重点介绍了操作相关的各个引数,帮助加强对Compaction的理解以及便于后续调参参考。参考
http://hbase.apache.org/book.html#compaction
https://mp.weixin.qq.com/s/ctnCm3uLCotgRpozbXmVMg
https://blog.csdn.net/cangencong/article/details/72763265
https://blog.csdn.net/shenshouniu/article/details/83902291
如果对您有帮助,欢迎关注微信公众号 cuteximi 、转发、收藏。
助力大资料学习、面试分享!





























