hbase是个比较吃内存的大数据组件,虽然数据存在hdfs中,但是不像mysql或者elasearch那样有索引的优势,只能用内存缓存数据来实现快速存取。
hbase安装时候,通常都需要修改配置文件,默认配置通常是8G内存的配置。
配置文件有问题的话,后果是:hbase集群启动,直接报错,启动失败。所以说,一个好的hbase内存配置,很重要。
数据组hbase好端端的,老是不够,然后非常协调的整个集群挂了,后来发现是机器64G内存升到96G的时候,我想当然的把32G堆内存改为64G,导致分配不到资源却不进行GC,一直向系统拿内存,集群就挂了。
后来,我们重新规划了一下内存,一直很坚挺。我们集群版本是这样的:
hadoop 3.0
hbase 2.0.3
注意:hbase1.x与2.x区别很大,无论是flush、compact,还是split上面,所以这里需要强调一下,版本是2.0.3,网上很多博客讲的是1.x版本的,2.x有很大改变,属于重大版本变更。hbase2.x相比1.x确实有很大的改变,比如:尽量使用offheap对外内存,官方还有一种说法,使用断电不丢数据的内存,来替换掉wal机制。版本很重要,区别很大。
这里主要介绍几个概念:
compact
flush
内存规划
HBase compaction主要是为了压缩存储空间,提高读写速度,根据合并规模将Compaction分为了两类:MinorCompaction和MajorCompaction
Minor Compaction是指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次Minor Compaction的结果是更少并且更大的StoreFile。
Major Compaction是指将所有的StoreFile合并成一个StoreFile,这个过程还会清理三类无意义数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。另外,一般情况下,Major Compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此线上业务都会将关闭自动触发Major Compaction功能,改为手动在业务低峰期触发。
minor compaction通常会由memstore flush,线程定期检查触发。major compaction通常会由手动触发,可以通过参数,hbase.hregion.majorcompaction设置为0即可,默认时间一天86400000。
进入hbase shell执行手动压缩命令。
minor compaction
hbase(main):009:0> help "compact"
Compact all regions in passed table or pass a region row
to compact an individual region. You can also compact a single column
family within a region.
You can also set compact type, "NORMAL" or "MOB", and default is "NORMAL"
Examples:
Compact all regions in a table:
hbase> compact 'ns1:t1'
hbase> compact 't1'
Compact an entire region:
hbase> compact 'r1'
Compact only a column family within a region:
hbase> compact 'r1', 'c1'
Compact a column family within a table:
hbase> compact 't1', 'c1'
Compact table with type "MOB"
hbase> compact 't1', nil, 'MOB'
Compact a column family using "MOB" type within a table
hbase> compact 't1', 'c1', 'MOB'
major compaction
hbase(main):003:0> help 'major_compact'
Run major compaction on passed table or pass a region row
to major compact an individual region. To compact a single
column family within a region specify the region name
followed by the column family name.
Examples:
Compact all regions in a table:
hbase> major_compact 't1'
hbase> major_compact 'ns1:t1'
Compact an entire region:
hbase> major_compact 'r1'
Compact a single column family within a region:
hbase> major_compact 'r1', 'c1'
Compact a single column family within a table:
hbase> major_compact 't1', 'c1'
Compact table with type "MOB"
hbase> major_compact 't1', nil, 'MOB'
Compact a column family using "MOB" type within a table
hbase> major_compact 't1', 'c1', 'MOB'
hbase写数据,一般先写wal,确认成功后,再写memstore,每个列族有一个memstore,当一个region所有family memstore大小之和达到一定大小(hbase.regionserver.global.memstore.size),这个值通常是默认128M,就会flush,当然一个family的memstore大小达到这个值也会flush的,这样做也是为了提高读写的效率。在2.0+版中,memstore其实是有一个可变的memstore和许多不可变的memstore组成,直接在内存中进行compaction,如果flush成HFile,再compaction,会占用大量磁盘和网络IO,这是一个改进。
hbase内存规划,需要结合实际业务,分为读多写少,还是读少写多,我们的业务是读少写多。通常,我们会错误估算了写,compaction、split、flush都要涉及到写。这里是我们业务读多写少的内存规划。主要是常见的64G机器与96G机器。
对BlockCache策略一直有这样的观点:RS内存在20G以内的就选择LRUBlockCache,大于20G的就选择BucketCache中的Offheap模式。接下来所有的相关配置都基于BucketCache的offheap模型进行说明。
序号 | 步骤 | 原理 | 计算公式 | 计算值 | 修正值 |
---|---|---|---|---|---|
A | 规划RS总内存 | 在系统内存允许且不影响其他服务的情况下,越多越好。64G内存,预留8G即可 | 64G - 8G | 56G | 56G |
B | 规划读缓存 CombinedBlockCache | 整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5 : 4 : 1的分配原则。读缓存设置为整个RS内存的50% | A(56G) * 50% | 28G | 28G |
B1 | 规划读缓存LRU部分 | LRU部分主要缓存数据块元数据,数据量相对较小。设置为整个读缓存的10% | B(28G)*10% | 2.8G | 3G |
B2 | 规划读缓存BucketCache部分 | BucketCache部分主要缓存用户数据块,数据量相对较大。设置为整个读缓存的90% | B(28G)*90% | 25.2G | 24G |
C | 规划写缓存MemStore | 整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5:4:1的分配原则。写缓存设置为整个RS内存的40% | A(56G) * 40% | 22.4G | 22G |
D | 设置JVM_HEAP | RS总内存大小 减去 堆外内存大小 | A – B2 | 30.8G | 32G |
注意
LRUBlockCache + MemStore < 80% * JVM_HEAP
hbase-env.sh
-Xmx32g -Xms32g -Xmn1g -Xss256k -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=75 -XX:-DisableExplicitGC
hbae-site.xml
hbase.regionserver.global.memstore.upperLimit
0.60
hbase.regionserver.global.memstore.lowerLimit
0.55
hfile.block.cache.size
0.19
hbase.bucketcache.ioengine
offheap
hbase.bucketcache.size
24576
hbase.bucketcache.percentage.in.combinedcache
0.90
序号 | 步骤 | 原理 | 计算公式 | 计算值 | 修正值 |
---|---|---|---|---|---|
A | 规划RS总内存 | 在系统内存允许且不影响其他服务的情况下,越多越好。96G内存,预留8G即可 | 96G - 8G | 88G | 88G |
B | 规划读缓存 CombinedBlockCache | 整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5 : 4 : 1的分配原则。读缓存设置为整个RS内存的50% | A(88G) * 50% | 44G | 44G |
B1 | 规划读缓存LRU部分 | LRU部分主要缓存数据块元数据,数据量相对较小。设置为整个读缓存的10% | B(44G)*10% | 4.4G | 4G |
B2 | 规划读缓存BucketCache部分 | BucketCache部分主要缓存用户数据块,数据量相对较大。设置为整个读缓存的90% | B(44G)*90% | 39.6G | 39G |
C | 规划写缓存MemStore | 整个RS内存分为三部分:读缓存、写缓存、其他。基本按照5:4:1的分配原则。写缓存设置为整个RS内存的40% | A(88G) * 40% | 35.2G | 35G |
D | 设置JVM_HEAP | RS总内存大小 减去 堆外内存大小 | A – B2 | 49G | 49G |
hbase-env.sh
export HBASE_HEAPSIZE=32768
#export master_heapsize=65536
export regionserver_heapsize=50176
export HBASE_REGIONSERVER_OPTS="-Xmx49g -Xms49g -Xmn2g -Xss256k -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -XX:-DisableExplicitGC"
hbase-site.xml
hbase.regionserver.global.memstore.upperLimit
0.6
hbase.regionserver.global.memstore.lowerLimit
0.55
hfile.block.cache.size
0.19
hbase.bucketcache.ioengine
offheap
hbase.bucketcache.size
39936
hbase.bucketcache.percentage.in.combinedcache
0.80
hbase.hregion.max.filesize
107374182400
具体内存分配,可以参考这几篇文章,写的非常不错。
HBase BlockCache系列 – 走进BlockCache(http://hbasefly.com/2016/04/08/hbase-blockcache-1/)
HBase BlockCache系列 - 探求BlockCache实现机制(http://hbasefly.com/2016/04/26/hbase-blockcache-2/)
HBase最佳实践-内存规划(http://hbasefly.com/2016/06/18/hbase-practise-ram/)强烈推荐
HBase最佳实践-聊聊HBase核心配置参数(https://sq.163yun.com/blog/article/170965000956645376)