从原理到参数解析,HBase 刷写与合并机制介绍

HBase 是目前主流的 NoSQL 数据库,是一个高可靠、高性能、高伸缩的分布式 KV 存储系统,本文讲解 HBase 两个核心机制——刷写(Flush)与合并(Compaction),重点介绍其原理及参数配置建议。

1、为什么要进行刷写和合并

HBase 是 Google BigTable 的开源实现,底层存储引擎是基于 LSM 树(Log-Structured Merge Tree)数据结构设计的。写入数据时会先写 WAL 日志,再将数据写到写缓存 MemStore 中,等写缓存达到一定规模或其他触发条件时会 Flush 刷写到磁盘,生成一个 HFile 文件,这样就将磁盘随机写变成了顺序写,提高了写性能。基本拓扑图:

随着时间推移,写入的 HFile 会越来越多,读取数据时就会因为要进行多次io导致性能降低,因此 HBase 会定期执行 Compaction 操作以合并减少 HFile 数量,提升读性能。

2、Flush 触发条件和参数

理解 Flush 的触发条件非常重要,从中我们也可以看出何时会阻塞写请求,总结有 7 种情况会触发 Flush:

  • 当一个 MemStore 大小达到阈值 hbase.hregion.memstore.flush.size(默认128M)时,会触发 MemStore 的刷写。这个时候不会阻塞写请求。

  • 当一个 Region 中所有 MemStore 总大小达到 hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size(默认4*128M=512M)时,会触发 MemStore 的刷写,并阻塞 Region 所有的写请求,此时写数据会出现 RegionTooBusyException 异常。

  • 当一个 RegionServer 中所有 MemStore 总大小达到 hbase.regionserver.global.memstore.size.lower.limit * hbase.regionserver.global.memstore.size * hbase_heapsize(低水位阈值,默认0.95 * 0.4 * RS 堆大小)时,会触发 RegionServer 中内存占用大的 MemStore 的刷写;达到 hbase.regionserver.global.memstore.size * hbase_heapsize(高水位阈值,默认0.4 * RS堆大小)时,不仅会触发 Memstore 的刷写,还会阻塞 RegionServer 所有的写请求,直到 Memstore 总大小降到低水位阈值以下。

  • 当一个 RegionServer 的 HLog 即WAL文件数量达到上限(可通过参数 hbase.regionserver.maxlogs 配置,默认32)时,也会触发 MemStore 的刷写,HBase 会找到最旧的 HLog 文件对应的 Region 进行刷写 。

  • 当一个 Region 的更新次数达到 hbase.regionserver.flush.per.changes(默认30000000即3千万)时,也会触发 MemStore 的刷写。

  •  定期 hbase.regionserver.optionalcacheflushinterval(默认3600000即一个小时)进行 MemStore 的刷写,确保 MemStore 不会长时间没有持久化。为避免所有的 MemStore 在同一时间进行 flush 而导致问题,定期的 flush 操作会有一定时间的随机延时。

  •  手动执行 flush 操作,我们可以通过 hbase shell 或 API 对一张表或一个 Region 进行 flush。

上面是 Flush 的几个触发条件,从中我们拿到 5 个和 Flush 有关的重要参数,并给出调整建议:

1、hbase.hregion.memstore.flush.size

默认值 128M,单个 MemStore 大小超过该阈值就会触发 Flush。如果当前集群 Flush 比较频繁,并且内存资源比较充裕,建议适当调整为 256M。调大的副作用可能是造成宕机时需要分裂的 HLog 数量变多,从而延长故障恢复时间。

2、hbase.hregion.memstore.block.multiplier

默认值 4,Region 中所有 MemStore 超过单个 MemStore 大小的倍数达到该参数值时,就会阻塞写请求并强制 Flush。一般不建议调整,但对于写入过快且内存充裕的场景,为避免写阻塞,可以适当调整到5~8。

3、hbase.regionserver.global.memstore.size

默认值 0.4,RegionServer 中所有 MemStore 大小总和最多占 RegionServer 堆内存的 40%。这是写缓存的总比例,可以根据实际场景适当调整,且要与 HBase 读缓存参数 hfile.block.cache.size(默认也是0.4)配合调整。旧版本参数名称为 hbase.regionserver.global.memstore.upperLimit。

4、hbase.regionserver.global.memstore.size.lower.limit

默认值 0.95,表示 RegionServer 中所有 MemStore 大小的低水位是 hbase.regionserver.global.memstore.size 的 95%,超过该比例就会强制 Flush。一般不建议调整。旧版本参数名称为 hbase.regionserver.global.memstore.lowerLimit。

5、hbase.regionserver.optionalcacheflushinterval

默认值 3600000(即 1 小时),HBase 定期 Flush 所有 MemStore 的时间间隔。一般建议调大,比如 10 小时,因为很多场景下 1 小时 Flush 一次会产生很多小文件,一方面导致 Flush 比较频繁,另一方面导致小文件很多,影响随机读性能,因此建议设置较大值。

上面就是 Flush 的触发条件及核心参数,理解并适当调整参数有利于维护 HBase 集群的稳定性。

3、Compaction 类型、触发时机和参数

从上面分析我们知道,HBase 会定期执行 Compaction 合并 HFile,提升读性能,其实就是以短时间内的io消耗,换取相对稳定的读取性能。

Compaction 类型

Compaction 分为两种:Minor Compaction 与 Major Compaction,可以称为小合并、大合并,简单示意图:

Minor Compaction 是指选取一些小的、相邻的 HFile 将他们合并成一个更大的 HFile。默认情况下,Minor Compaction 会删除选取 HFile 中的 TTL 过期数据。

Major Compaction 是指将一个 Store 中所有的 HFile 合并成一个 HFile,这个过程会清理三类没有意义的数据:被删除的数据(打了 Delete 标记的数据)、TTL 过期数据、版本号超过设定版本号的数据。另外,一般情况下,Major Compaction 时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此,生产环境下通常关闭自动触发 Major Compaction 功能,改为手动在业务低峰期触发。

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 服务端线程唤醒时间间隔,用于 LogRoller、MemStoreFlusher 等的周期性检查;参数 hbase.server.compactchecker.interval.multiplier 默认值1000,是 Compaction 操作周期性检查乘数因子,10 * 1000 s 时间上约等于2hrs, 46mins, 40sec。

  • 手动触发:通过 HBase Shell、Master UI 界面或 HBase API 等任一种方式执行 compact、major_compact等命令,会立即触发 Compaction。

Compaction 核心参数

和上面类似,这里总结了几个和 Compaction 有关的重要参数,并给出调整建议:

1、hbase.hstore.compaction.min

默认值 3,一个 Store 中 HFile 文件数量超过该阈值就会触发一次 Compaction(Minor Compaction),这里称该参数为 minFilesToCompact。一般不建议调小,重写场景下可以调大该参数,比如 5~10 之间,注意相应调整下一个参数。老版本参数名称为 hbase.hstore.compactionthreshold。

2、hbase.hstore.compaction.max

默认值 10,一次 Minor Compaction 最多合并的 HFile 文件数量,这里称该参数为 maxFilesToCompact。这个参数也控制着一次压缩的耗时。一般不建议调整,但如果上一个参数调整了,该参数也应该相应调整,一般设为 minFilesToCompact 的 2~3 倍。

3、hbase.regionserver.thread.compaction.throttle

HBase RegionServer 内部设计了两个线程池 large compactions 与 small compactions,用来分离处理 Compaction 操作,该参数就是控制一个 Compaction 交由哪一个线程池处理,默认值是 2 * maxFilesToCompact * hbase.hregion.memstore.flush.size(默认2*10*128M=2560M即2.5G),建议不调整或稍微调大。

4、hbase.regionserver.thread.compaction.large/small

默认值 1,表示 large compactions 与 small compactions 线程池的大小。一般建议调整到 2~5,不建议再调太大比如10,否则可能会消费过多的服务端资源造成不良影响。

5、hbase.hstore.blockingStoreFiles

默认值 10,表示一个 Store 中 HFile 文件数量达到该值就会阻塞写入,等待 Compaction 的完成。一般建议调大点,比如设置为 100,避免出现阻塞更新的情况,阻塞日志如下:

too many store files; delaying flush up to 90000ms

生产环境建议认真根据实际业务量做好集群规模评估,如果小集群遇到了持续写入过快的场景,合理扩展集群也非常重要。

6、hbase.hregion.majorcompaction

默认值 604800000 ms 即7天,这是 Major Compaction 周期性触发执行的时间间隔。通常 Major Compaction 持续时间较长、资源消耗较大,一般设为 0,表示关闭自动触发,建议在业务低峰期时手动执行。

4、总结

本文概括的介绍了 HBase 的刷写和合并机制,主要是 Flush 的触发条件与核心参数、Compaction 的触发时机与核心参数等,并都给出了具体参数的调整建议,希望能给 HBase 使用者提供有价值的参考。

邀请你一起来讨论

???? ???? ????

往期推荐

HBase二次开发之搭建HBase调试环境,如何远程debug HBase源代码

【生活现场】从洗袜子到HBase存储原理解析

HBase的ACL说明

HBase配置AES加密

HBase原理(一):架构理解

如何将Hive与HBase整合联用

Python生成HBase 10w+ 条数据说明

HBase应用(一):数据批量导入说明

HBase 集成 Phoenix 构建二级索引实践

HBase漫谈 | HBase分区过多影响&合理分区数量

HBase 性能调优第一弹:内存篇

扫一扫,我们的故事就开始了。

如果这篇文章对你有所启发,点赞、转发都是一种支持!

另外公众号改变了推送规则,大家看文章不要忘记点击最下方的在看,点赞按钮,这样微信自动识别为常看公众号,否则很可能推送的文章可能淹没在别的文章找不到,谢谢大家

让我知道你在看

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值