HBase最佳实践-内存规划

简介:

线上HBase集群应该如何进行参数配置?这其实是很多HBase初学者在实践环节都可能会遇到的问题,有些人会选择默认配置,有些人会选择其他公司的推荐配置;诚然,这样的参数配置在大多数情况下都能正常工作,但性能却未必最佳、资源未必都能被合理利用。本文结合笔者的实践经验,针对不同应用场景,对多种工作模式下的参数进行详细说明,并结合相关示例对集群规划中最核心模块-内存规划进行介绍。一方面希望读者能够了解HBase内存相关知识细节,另一方面能够将这些知识应用于实践、不断对集群进行优化。

HBase中内存规划直接涉及读缓存BlockCache、写缓存MemStore,影响系统内存利用率、IO利用率等资源以及读写性能等,重要性不言而喻。主要配置也是针对BlockCache和MemStore进行,然而针对不同业务类型(简单说来主要包括读多写少型和写多读少型),内存的相关配置却完全不同。再者,对于读缓存BlockCache,线上一般会有两种工作模式:LRUBlockCache和BucketCache,不同工作模式下的相关配置也不尽相同。为了比较完整的说明不同应用场景以及不同缓存工作模式的内存规划,下文会分分别介绍两个案列:读多写少型+BucketCache,写多读少型+LRUBlockCache。

需要说明的是,业务类型和读缓存工作模式之间没有任何直接的关联。业务到底使用BucketCache还是使用LRUBlockCache,只和分配给RegionServer的内存大小有关。一般而言,如果HBASE_HEAPSIZE > 20G,选择BucketCache,否则选择LRUBlockCache(参考hortonworks文档),理论依据可以参考这里

案例一:写多读少型 + LRUBlockCache

内存分布图

在详细说明具体的容量规划前,首先需要明确LRUBlockCache模式下的内存分布图,如下图所示:



f1

图中分配给RegionServer进程的内存就是JVM内存,主要分为三部分:LRUBlockCache,用于读缓存;MemStore,用于写缓存;Other,用于RS运行所必须的其他对象;

内存规划思路

了解了BucketCache模式下的内存分布图之后,我们具体来分析如何规划内存,首先列出来基本条件:

a.  整个物理机内存:96G

b.  业务负载分布:30%读,70%写

接下来将问题一步一步分解,从上至下按照逻辑对内存进行规划:

(1) 系统内存基础上如何规划RS内存?

这个问题需要根据自身服务器情况决定,一般情况下,在不影响其他服务的情况下,越大越好。我们目前设置为64G,为系统内存的2/3。

(2) 如何设置LRUBlockCache、MemStore?

确定RegionServer总内存之后,接下来分别规划LRUBlockCahce和MemStore的总内存。在此需要考虑两点:在写多读少的业务场景下,写缓存显然应该分配更多内存,读缓存相对分配更少;HBase在此处有个硬规定:LRUBlockCache + MemStore < 80% * JVM_HEAP,否则RS无法启动。

推荐内存规划:MemStore = 45% * JVM_HEAP = 64G * 45% = 28.8G ,LRUBlockCache = 30% * JVM_HEAP = 64G * 30% = 19.2G;默认情况下Memstore为40% * JVM_HEAP,而LRUBlockCache为25% * JVM_HEAP

 配置设置实践

(1)设置JVM参数如下:

-XX:SurvivorRatio=2  -XX:+PrintGCDateStamps  -Xloggc:$HBASE_LOG_DIR/gc-regionserver.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=512M -server -Xmx64g -Xms64g -Xmn2g -Xss256k -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseParNewGC -XX:MaxTenuringThreshold=15  -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -XX:-DisableExplicitGC

(2)hbase-site.xml中MemStore相关参数设置如下:

<property>
    <name>hbase.regionserver.global.memstore.upperLimit</name>
    <value>0.45</value>
</property>
<property>
    <name>hbase.regionserver.global.memstore.lowerLimit</name>
    <value>0.40</value>
</property>

由上述定义可知,hbase.regionserver.global.memstore.upperLimit设置为0.45,hbase.regionserver.global.memstore.lowerLimit设置为0.40hbase.regionserver.global.memstore.upperLimit表示RegionServer中所有MemStore占有内存在JVM内存中的比例上限。如果所占比例超过这个值,RS会首先将所有Region按照MemStore大小排序,并按照由大到小的顺序依次执行flush,直至所有MemStore内存总大小小于hbase.regionserver.global.memstore.lowerLimit,一般lowerLimit比upperLimit小5%。

(3)hbase-site.xml中LRUBlockCache相关参数设置如下:

<property>
    <name>hfile.block.cache.size</name>
    <value>0.3</value>
</property>

hfile.block.cache.size表示LRUBlockCache占用内存在JVM内存中的比例,因此设置为0.3

案例二:读多写少型 + BucketCache

内存分布图

与LRUBlockCache模式相比,BucketCache模式下的内存分布图会更加复杂,如下图所示:

f2

如图,整个RegionServer内存(Java进程内存)分为两部分:JVM内存和堆外内存。其中JVM内存中LRUBlockCache和堆外内存BucketCache一起构成了读缓存CombinedBlockCache,用于缓存读到的Block数据,其中LRUBlockCache用于缓存元数据Block,BucketCache用于缓存实际用户数据Block;MemStore用于写流程,缓存用户写入KeyValue数据;还有部分用于RegionServer正常运行所必须的内存;

内存规划思路

和案例一相同,本案例中物理机内存也是96G,不过业务类型为读多写少:70%读+30%写

因为BucketCache模式下内存分布图相对复杂,我们使用如下表格一步一步对内存规划进行解析:

序号

步骤

原理

计算公式

计算值

修正值

A

规划RS总内存 

在系统内存允许且不影响其他服务的情况下,越多越好。设置为系统总内存的 2/3。

2/3 * 96G

64G

64G

B

规划读缓存 CombinedBlockCache

整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5 : 3 : 2的分配原则。读缓存设置为整个RS内存的50%

A * 50%

32G

34G

B1

规划读缓存LRU部分

LRU部分主要缓存数据块元数据,数据量相对较小。设置为整个读缓存的10%

B * 10%

3.2G

3G

B2

规划读缓存BucketCache部分

BucketCache部分主要缓存用户数据块,数据量相对较大。设置为整个读缓存的90%

B * 90%

28.8G

30G

C

规划写缓存MemStore

整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5:4:1的分配原则。写缓存设置为整个RS内存的40%

A * 30%

19.2G

20G

D

设置JVM_HEAP

RS总内存大小 – 堆外内存大小

A – B2 

35.2G

30G

计算修正

看到这里,可能很多仔细的朋友就会疑问,案例一不是说过HBase有一个硬规定么:LRUBlockCache + MemStore < 80% * JVM_HEAP,否则RS无法启动。不错,HBase确实有这样一个规定,这个规定的本质是为了在内存规划的时候能够给除过写缓存和读缓存之外的其他对象留够至少20%的内存空间。那按照上述计算方式能不能满足这个硬规定呢,LRU + MemStore / JVM_HEAP = 3.2G + 19.2G / 35.2G = 22.4G / 35.2G =  63.6% ,远小于80%。因此需要对计算值进行简单的修正,适量减少JVM_HEAP值(减少至30G),增大Memstore到20G。因为JVM_HEAP减少了,堆外内存就需要适量增大,因此将BucketCache增大到30G。


调整之后,LRU + MemStore / JVM_HEAP = 3.2G + 20G / 30G = 23.2G / 30G =  77%

 配置设置实践

(1)设置JVM参数如下:

-XX:SurvivorRatio=2  -XX:+PrintGCDateStamps  -Xloggc:$HBASE_LOG_DIR/gc-regionserver.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=512M -server -Xmx40g -Xms40g -Xmn1g -Xss256k -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseParNewGC -XX:MaxTenuringThreshold=15  -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -XX:-DisableExplicitGC

(2)hbase-site.xml中MemStore相关参数设置如下:

<property>
    <name>hbase.regionserver.global.memstore.upperLimit</name>
    <value>0.66</value>
</property>
<property>
    <name>hbase.regionserver.global.memstore.lowerLimit</name>
    <value>0.60</value>
</property>

根据upperLimit参数的定义,结合上述内存规划数据可计算出 upperLimit =  20G / 30G = 66%。因此upperLimit参数设置为0.66,lowerLimit设置为0.60

(3)hbase-site.xml中CombinedBlockCache相关参数设置如下:

<property>
    <name>hbase.bucketcache.ioengine</name>
    <value>offheap</value>
</property>
<property>
    <name>hbase.bucketcache.size</name>
    <value>34816</value>
</property>
<property>
    <name>hbase.bucketcache.percentage.in.combinedcache</name>
    <value>0.90</value>
</property>

按照上述介绍设置之后,所有关于内存相关的配置基本就完成了。但是需要特别关注一个参数hfile.block.cache.size,这个参数在本案例中并不需要设置,没有任何意义。但是HBase的硬规定却是按照这个参数计算的,这个参数的值加上hbase.regionserver.global.memstore.upperLimit的值不能大于0.8,上文提到hbase.regionserver.global.memstore.upperLimit值设置为0.66,因此,hfile.block.cache.size必须设置为一个小于0.14的任意值。hbase.bucketcache.ioengine表示bucketcache设置为offheap模式;hbase.bucketcache.size表示所有读缓存占用内存大小,该值可以为内存真实值,单位为M,也可以为比例值,表示读缓存大小占JVM内存大小比例。如果为内存真实值,则为34G,即34816。hbase.bucketcache.percentage.in.combinedcache参数表示用于缓存用户数据块的内存(堆外内存)占所有读缓存的比例,设为0.90;

至此,关于HBase集群的内存规划经过两个案例的分析到此就要结束了,希望看官能够理解整个分析的思路。结合自己的应用场景以及内存使用模式对内存进行规划。本文也只是笔者个人见解,如果有任何意见可以相互交流讨论


本文转载自:http://hbasefly.com

原文链接

相关实践学习
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
存储 缓存 固态存储
HBase 性能调优第一弹:内存篇
这是使用 HBase 最不可避免的一个话题,就是 HBase 的性能调优,而且通常建立在我们对 HBase 内部运行机制比较了解的基础上进行的,因此无论怎么说,调优这块都是一个相对复杂的事情。这一篇我们先来介绍与 HBase 内存最相关的调优内容。 1. 合理配置 JVM 内存 这里首先涉及 HBase 服务的堆内存设置。一般刚部署的 HBase 集群,默认配置只给 Master 和 RegionServer 分配了 1G 的内存,RegionServer 中 MemStore 默认占 0.4 即 400MB 左右的空间,而一个 MemStore 刷写阈值默认 128M,所以一个 Regi
768 0
|
云安全 Java Shell
EMR主节点内存异常100%,hbase服务异常
EMR主节点内存异常100%,hbase服务异常
|
SQL 搜索推荐 Java
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
406 0
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
|
存储 缓存 算法
生产环境使用HBase,你必须知道的最佳实践
生产环境使用HBase,你必须知道的最佳实践
249 0
|
存储 SQL 缓存
图文详解:内存总是不够,我靠HBase说服了Leader为新项目保驾护航
大家好,我是小羽最近在工作中用到了 Hbase 这个数据库,也顺便做了关于 Hbase 的知识记录来分享给大家。其实 Hbase的内容体系真的很多很多,这里介绍的是小羽认为在工作中会用到...
176 0
|
并行计算
CUDA C 最佳实践:优化主机和设备之间的内存传输【读书笔记】
CUDA C 最佳实践:优化主机和设备之间的内存传输【读书笔记】
76 0
CUDA C 最佳实践:优化主机和设备之间的内存传输【读书笔记】
|
算法 Java
SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践
SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践
145 0
|
存储 缓存 算法
生产环境使用HBase,你必须知道的最佳实践
前面,我们已经打下了很多关于HBase的理论基础,今天,我们主要聊聊在实际开发使用HBase中,需要关注的一些最佳实践经验。 1.Schema设计七大原则 1)每个region的大小应该控制在10G到50G之间; 2)一个表最好保持在 50到100个 region的规模; 3)每个cell最大不应该超过10MB,如果超过,应该有些考虑业务拆分,如果实在无法拆分,那就只能使用mob; 4)跟传统的关系型数据库不同,一个HBase的表中列族最多不超过3个,列族中的列可以动态添加的,不要设计过多列族; 5)列族名必须尽量短,因为我们知道在存储的时候,每个keyvalue都会包含列族名;
152 0
|
存储 弹性计算 NoSQL
非易失性内存实例构建高性价比Redis服务器最佳实践
使用非易失性内存(AEP)实例构建大容量低成本的Redis服务器,提升性价比。
非易失性内存实例构建高性价比Redis服务器最佳实践
|
机器学习/深度学习 SQL 分布式计算
云HBase Phoenix索引构建最佳实践
介绍三种的不同的索引构建方法及其适用场景
2587 0

热门文章

最新文章