//简单说来主要包括读多写少型和写多读少型),内存的相关配置却完全不同。

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

提示: 1、需要说明的是,业务类型和读缓存工作模式之间没有任何直接的关联。 2、业务到底使用BucketCache还是使用LRUBlockCache,只和分配给RegionServer的内存大小有关。 3、一般而言,如果HBASE_HEAPSIZE > 20G,选择BucketCache,否则选择LRUBlockCache(参考hortonworks文档), //注意在cdh中的hbase默认都是bucketcache缓存机制。

案例一:写多读少型 + LRUBlockCache //必须见博客,此处笔记做的不详细 LRUBlockCache模式下的内存分布图 图中分配给RegionServer进程的内存就是JVM内存,主要分为三部分:LRUBlockCache,用于读缓存;MemStore,用于写缓存;Other,用于RS运行所必须的其他对象;

内存规划思路 了解了LRUBlockCache模式下的内存分布图之后,我们具体来分析如何规划内存,首先列出来基本条件: a. 整个物理机内存:96G b. 业务负载分布:30%读,70%写 接下来将问题一步一步分解,从上至下按照逻辑对内存进行规划: (1) 系统内存基础上如何规划RS内存? 1、这个问题需要根据自身服务器情况决定,一般情况下,在不影响其他服务的情况下,越大越好。我们目前设置为64G,为系统内存的2/3。 (2) 如何设置LRUBlockCache、MemStore? 1、确定RegionServer总内存之后,接下来分别规划LRUBlockCahce和MemStore的总内存。 2、在此需要考虑两点:在写多读少的业务场景下,写缓存显然应该分配更多内存,读缓存相对分配更少; 3、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>

由上述定义可知: 1、hbase.regionserver.global.memstore.upperLimit设置为0.45, 2、hbase.regionserver.global.memstore.lowerLimit设置为0.40 3、hbase.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 //提示:以上这些参数在cdh都有 *****


案例二:读多写少型 + BucketCache //必须看博客详细内容 太经典了

BucketCache模式下的内存分布图


1、与LRUBlockCache模式相比,BucketCache模式下的内存分布图会更加复杂 细节,需要结合图形来看 1、整个RegionServer内存(Java进程内存)分为两部分:JVM内存和堆外内存。 2、其中JVM内存中LRUBlockCache和堆外内存BucketCache一起构成了读缓存CombinedBlockCache,用于缓存读到的Block数据, 3、其中LRUBlockCache用于缓存元数据Block, 4、BucketCache用于缓存实际用户数据Block; 5、MemStore用于写流程,缓存用户写入KeyValue数据; 6、还有部分用于RegionServer正常运行所必须的内存; 内存规划思路 和案例一相同,本案例中物理机内存也是96G,不过业务类型为读多写少:70%读+30%写

计算修正

看到这里,可能很多仔细的朋友就会疑问,案例一不是说过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>

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

写的太好了,必须要看博客的原文

小伙伴问的问题1: 博主,你好! 请问下,你们生产上给region server的 jvm堆大小 是 超过32G (比如 70G+)的么? 我们生产上按照服务商提供的意见,只给了20G。理由主要是怕内存太大,一旦发生CMS full GC,导致STW时间过长,从而引起集群故障的风险。 但是,我们夜间有较大量的数据写入(通过spark程序进行putlist),通过监控发现,期间会发生大量的CMS full gc。 目前调优建议是,将region server堆内存调制 32G,新生代给 2G(PS, 你之前CMS GC调优的文章也看过哈)。这也需要进一步测试看效果。目的是要减少CMS Full GC,减少STW的时间。 目前集群单机内存是192G,是和hbase和其他组件 yarn(主要跑spark任务)等 共用的,除了基础组件外,yarn大概分了剩下的130G。 想请问下,你们在给region server分配大内存上面的经验,比如给到(60 – 70G),风险情况如何呢?比如,给到这样大量的内存,然后调低memstore和blockcache的占用比,然后这样使得CMS Full GC 基本不发生,这种思路的方案,你觉得可行么? 谢谢! 答: 大堆小米有一个使用G1GC的分享,可以降低Full GC的风险。G1GC的参数调优是个技术活,可以参考这篇文章看看http://hbase-help.com/?/article/6 。 或者可以在一台机器上起多个RS。

写的太好了,必须要看博客的原文

参考链接: HBase最佳实践-内存规划 http://hbasefly.com/2016/06/18/hbase-practise-ram/ ***** //必须见博客