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

简介: 这是使用 HBase 最不可避免的一个话题,就是 HBase 的性能调优,而且通常建立在我们对 HBase 内部运行机制比较了解的基础上进行的,因此无论怎么说,调优这块都是一个相对复杂的事情。这一篇我们先来介绍与 HBase 内存最相关的调优内容。1. 合理配置 JVM 内存这里首先涉及 HBase 服务的堆内存设置。一般刚部署的 HBase 集群,默认配置只给 Master 和 RegionServer 分配了 1G 的内存,RegionServer 中 MemStore 默认占 0.4 即 400MB 左右的空间,而一个 MemStore 刷写阈值默认 128M,所以一个 Regi

这是使用 HBase 最不可避免的一个话题,就是 HBase 的性能调优,而且通常建立在我们对 HBase 内部运行机制比较了解的基础上进行的,因此无论怎么说,调优这块都是一个相对复杂的事情。这一篇我们先来介绍与 HBase 内存最相关的调优内容。

  1. 合理配置 JVM 内存

这里首先涉及 HBase 服务的堆内存设置。一般刚部署的 HBase 集群,默认配置只给 Master 和 RegionServer 分配了 1G 的内存,RegionServer 中 MemStore 默认占 0.4 即 400MB 左右的空间,而一个 MemStore 刷写阈值默认 128M,所以一个 RegionServer 也就能正常管理 3 个Region,多了就可能会产生小文件了,另外也容易发生 Full GC。因此建议合理调整 Master 和 RegionServer 的内存,比如:

export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -Xms8g -Xmx8g"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -Xms32g -Xmx32g"
这里也要根据实际集群资源进行配置,另外要牢记至少留 10% 的内存给操作系统使用。

  1. 选择合适的 GC 策略

另一个重要方面是 HBase JVM 的 GC 优化,其实 HBase 读写路径上的很多设计都是围绕 GC 优化做的。选择合适的 GC 策略非常重要,对于 HBase 而言通常有两种可选 GC 方案:

ParallelGC 和 CMS 组合
G1GC
而 CMS 和 G1 有什么区别呢?

CMS 避免不了 Full GC,而且 Full GC 场景下会通过一次串行的完整垃圾收集来回收碎片化的内存,这个过程通常会比较长,应用线程会发生长时间的 STW 停顿,不响应任何请求;而 G1 适合大内存的场景,通过把堆内存划分为多个 Region(不是 HBase 中的 Region),然后对各个 Region 单独进行 GC,这样就具有了并行整理内存碎片的功能,可以最大限度的避免 Full GC 的到来,提供更加合理的停顿时间。

由于 Master 只是做一些管理操作,实际处理读写请求和存储数据的都是 RegionServer 节点,所以一般内存问题都出在 RegionServer 上。

这里给的建议是,小堆(4G及以下)选择 CMS,大堆(32G及以上)考虑用 G1,如果堆内存介入 4~32G 之间,可自行测试下两种方案。剩下来的就是 GC 参数调优了,这一块也要合理配置加上实际测试,后面再单独聊这块。

  1. 开启 MSLAB 功能

这是 HBase 自己实现了一套以 MemStore 为最小单元的内存管理机制,称为 MSLAB(MemStore-Local Allocation Buffer),主要作用是为了减少内存碎片化,改善 Full GC 发生的情况。

MemStore 会在内部维护一个 2M 大小的 Chunk 数组,当写入数据时会先申请 2M 的 Chunk,将实际数据写入该 Chunk中,当该 Chunk 满了以后会再申请一个新的 Chunk。这样 MemStore Flush 后会达到粗粒度化的内存碎片效果,可以有效降低 Full GC 的触发频率。

HBase 默认是开启 MSLAB 功能的,和 MSLAB 相关的配置包括:

hbase.hregion.memstore.mslab.enabled:MSLAB 开关,默认为 true,即打开 MSLAB。
hbase.hregion.memstore.mslab.chunksize:每个 Chunk 的大 小,默认为 2MB,建议保持默认值。
hbase.hregion.memstore.chunkpool.maxsize:内部 Chunk Pool 功能,默认为 0 ,即关闭 Chunk Pool 功能。设置为大于 0 的值才能开启,取值范围为 [0,1],表示 Chunk Pool 占整个 MemStore 内存大小的比例。
hbase.hregion.memstore.chunkpool.initialsize:表示初始化时申请多少个 Chunk 放到 Chunk Pool 中,默认为 0,即初始化时不申请 Chuck,只在写入数据时才申请。
hbase.hregion.memstore.mslab.max.allocation:表示能放入 MSLAB 的最大单元格大小,默认为 256KB,超过该大小的数据将从 JVM 堆分配空间而不是 MSLAB。
出于性能优化考虑,建议检查卖手游平台相关配置,确保 MSLAB 处于开启状态。

  1. 考虑开启 BucketCache

这块涉及到读缓存 BlockCache 的策略选择。首先,BlockCache 是 RegionServer 级别的,一个 RegionServer 只有一个 BlockCache。BlockCache 的工作原理是读请求会首先检查 Block 是否存在于 BlockCache,存在就直接返回,如果不存在再去 HFile 和 MemStore 中获取,返回数据时把 Block 缓存到 BlockCache 中,后续同一请求或临近查询可以直接从 BlockCache 中获取,避免过多的昂贵 IO 操作。BlockCache 默认是开启的。

目前 BlockCache 的实现方案有三种:

LRUBlockCache

最早的 BlockCache 方案,也是 HBase 目前默认的方案。LRU 是 Least Recently Used 的缩写,称为近期最少使用算法。LRUBlockCache 参考了 JVM 分代设计的思想,采用了缓存分层设计。

LRUBlockCache 将整个 BlockCache 分为 single-access(单次读取区)、multi-access(多次读取区)和 in-memory 三部分,默认分别占读缓存的25%、50%、25%。其中设置 IN_MEMORY=true 的列族,Block 被读取后才会直接放到 in-memory 区,因此建议只给那些数据量少且访问频繁的列族设置 IN_MEMORY 属性。另外,HBase 元数据比如 meta 表、namespace 表也都缓存在 in-memory 区。

SlabCache

HBase 0.92 版本引入的一种方案,起初是为了避免 Full GC 而引入的一种堆外内存方案,并与 LRUBlockCache 搭配使用,后来发现它对 Full GC 的改善很小,以至于这个方案基本被弃用了。

BucketCache

HBase 0.96 版本引入的一种方案,它借鉴了 SlabCache 的设计思想,是一种非常高效的缓存方案。实际应用中,HBase 将 BucketCache 和 LRUBlockCache 搭配使用,称为组合模式(CombinedBlockCahce),具体地说就是把不同类型的 Block 分别放到 LRUBlockCache 和 BucketCache 中。

HBase 会把 Index Block 和 Bloom Block 放到 LRUBlockCache 中,将 Data Block 放到 BucketCache 中,所以读取数据会去 LRUBlockCache 查询一下 Index Block,然后再去 BucketCache 中查询真正的数据。

BucketCache 涉及的常用参数有:

hbase.bucketcache.ioengine:使用的存储介质,可设置为 heap、offheap 或 file,其中 heap 表示空间从JVM堆中申请,offheap 表示使用 DirectByteBuffer 技术实现堆外内存管理,file 表示使用类似 SSD 等存储介质缓存数据。默认值为空,即关闭 BucketCache,一般建议开启 BucketCache。此外,HBase 2.x 不再支持 heap 选型。
hbase.bucketcache.combinedcache.enabled:是否打开 CombinedBlockCache 组合模式,默认为 true。此外,HBase 2.x 不再支持该参数。
hbase.bucketcache.size:BucketCache 大小,取值有两种,一种是[0,1]之间的浮点数值,表示占总内存的百分比,另一种是大于1的值,表示占用内存大小,单位 MB。
根据上面的分析,一般建议开启 BucketCache,综合考虑成本和性能,建议比较合理的介质是:LRUBlockCache 使用内存,BuckectCache 使用SSD,HFile 使用机械磁盘。

  1. 合理配置读写缓存比例

HBase 为了优化性能,在读写路径上分别设置了读缓存和写缓存,参数分别是 hfile.block.cache.size 与 hbase.regionserver.global.memstore.size,默认值都是 0.4,表示读写缓存各占 RegionServer 堆内存的 40%。

在一些场景下,我们可以适当调整两部分比例,比如写多读少的场景下我们可以适当调大写缓存,让 HBase 更好的支持写业务,相反类似,总之两个参数要配合调整。

  1. 总结

本文总结了与 HBase 内存最相关的调优内容,主要包括 JVM 内存大小设置,选择合适的 GC 策略,建议开启 MSLAB 与 BucketCache,以及合理配置读写缓存比例等内容,希望通过本文我们对于 HBase 性能调优有了一定的认识。

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
  相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情: https://cn.aliyun.com/product/hbase   ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
存储 缓存 监控
|
8天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
10天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
32 6
|
10天前
|
监控 安全 程序员
如何使用内存池池来优化应用程序性能
如何使用内存池池来优化应用程序性能
|
13天前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
1月前
|
存储 缓存 监控
Linux中内存和性能问题
【10月更文挑战第5天】
38 4
|
1月前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
2月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
24天前
|
存储 分布式计算 安全
阿里云服务器内存型r7、内存型r8y、内存型r8i实例规格性能对比与选择参考
在选择阿里云服务器实例规格时,针对内存密集型应用和数据库应用,内存型r7、内存型r8y和内存型r8i实例是这部分应用场景选择最多的热门实例规格。为了帮助大家更好地了解这三款实例的区别,并为选择提供参考,本文将详细对比它们的实例规格、CPU、内存、计算、存储、网络等方面的性能,并附上活动价格对比。让大家了解一下他们之间的不同,以供参考选择。
|
1月前
|
算法 Java
JVM进阶调优系列(3)堆内存的对象什么时候被回收?
堆对象的生命周期是咋样的?什么时候被回收,回收前又如何流转?具体又是被如何回收?今天重点讲对象GC,看完这篇就全都明白了。