热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HBase内存配置及JVM优化

前言本文从HBase的内存布局说起,先充分了解HBase的内存区的使用与分配,随后给出了不同业务场景下的读写内存分配规划,并指导如何分析业务的内存使用情况,以及在使用当中写内存Me

前言

本文从HBase的内存布局说起,先充分了解HBase的内存区的使用与分配,随后给出了不同业务场景下的读写内存分配规划,并指导如何分析业务的内存使用情况,以及在使用当中写内存Memstore及读内存扩展bucketcache的一些注意事项,最后为了保障群集的稳定性减少和降低GC对于集群稳定性的影响,研究及分享了一些关于HBase JVM配置的一些关键参数机器作用和范例,希望这些不断充实的经验能确保HBase集群的稳定性能更上一个台阶,大家有任何的想法和建议也欢迎一起讨论。


HBase的内存布局

一台region server的内存使用(如下图所示)主要分成两部分:

1.JVM内存即我们通常俗称的堆内内存,这块内存区域的大小分配在HBase的环境脚本中设置,在堆内内存中主要有三块内存区域,



  • 20%分配给hbase regionserver rpc请求队列及一些其他操作

  • 80%分配给memstore + blockcache

2.java direct memory即堆外内存,



  • 其中一部分内存用于HDFS SCR/NIO操作

  • 另一部分用于堆外内存bucket cache,其内存大小的分配同样在hbase的环境变量脚本中实现


读写内存规划



  • 写多读少型规划

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

如图,整个RegionServer内存就是JVM所管理的内存,BlockCache用于读缓存;MemStore用于写流程,缓存用户写入KeyValue数据;还有部分用于RegionServer正常RPC请求运行所必须的内存;































步骤原理计算
jvm_heap系统总内存的 2/3128G/3*280G
blockcache读缓存80G*30%24G
memstore写缓存80G*45%36G

hbase-site.xmll


hbase.regionserver.global.memstore.size
0.45


hfile.block.cache.size
0.3



  • 读多写少型规划

与 on heap模式相比,读多写少型需要更多的读缓存,在对读请求响应时间没有太严苛的情况下,会开启off heap即启用堆外内存的中的bucket cache作为读缓存的补充,如下图所示

整个RegionServer内存分为两部分:JVM内存和堆外内存。其中JVM内存中BlockCache和堆外内存BucketCache一起构成了读缓存CombinedBlockCache,用于缓存读到的Block数据,其中BlockCache用于缓存Index Block和Bloom Block,BucketCache用于缓存实际用户数据Data Block

















































步骤原理计算
RS总内存系统总内存的 2/3128G/3*280G
combinedBlockCache读缓存设置为整个RS内存的70%80G*70%56G
blockcache主要缓存数据块元数据,数据量相对较小。设置为整个读缓存的10%56G*10%6G
bucketcache主要缓存用户数据块,数据量相对较大。设置为整个读缓存的90%56G*90%50G
memstore写缓存设置为jvm_heap的60%30G*60%18G
jvm_heaprs总内存-堆外内存80G-50G30G

参数详解





































PropertyDefaultDescription
hbase.bucketcache.combinedcache.enabledtrueWhen BucketCache is enabled, use it as a L2 cache for LruBlockCache. If set to true, indexes and Bloom filters are kept in the LruBlockCache and the data blocks are kept in the BucketCache.
hbase.bucketcache.ioenginenoneWhere to store the contents of the BucketCache. Its value can be offheap、heap、file
hfile.block.cache.size0.4A float between 0.0 and 1.0. This factor multiplied by the Java heap size is the size of the L1 cache. In other words, the percentage of the Java heap to use for the L1 cache.
hbase.bucketcache.sizenot setWhen using BucketCache, this is a float that represents one of two different values, depending on whether it is a floating-point decimal less than 1.0 or an integer greater than 1.0.


  • If less than 1.0, it represents a percentage of total heap memory size to give to the cache.

  • If greater than 1.0, it represents the capacity of the cache in megabytes

  • -XX:MaxDirectMemorySizeMaxDirectMemorySize = BucketCache + 1A JVM option to configure the maximum amount of direct memory available for the JVM. It is automatically calculated and configured based on the following formula: MaxDirectMemorySize = BucketCache size + 1 GB for other features using direct memory, such as DFSClient. For example, if the BucketCache size is 8 GB, it will be -XX:MaxDirectMemorySize=9G.

    hbase-site.xml


    hbase.bucketcache.combinedcache.enabled
    true


    hbase.bucketcache.ioengine
    offheap #同时作为master的rs要用heap


    hbase.bucketcache.size
    50176 #单位MB。这个值至少要比bucketcache小1G,作为master的rs用heap,那么这里要填<1的值作为从heap中分配给bucketcache的百分比


    hbase.regionserver.global.memstore.size
    0.60 #heap减小了,那么heap中用于memstore的百分比要增大才能保证用于memstore的内存和原来一样


    hfile.block.cache.size
    0.20 #使用了bucketcache作为blockcache的一部分,那么heap中用于blockcache的百分比可以减小

    hbase-env.sh

    export HBASE_REGIONSERVER_OPTS="-XX:+UseG1GC
    -Xms30g –Xmx30g -XX:MaxDirectMemorySize=50g

    读写内存的使用情况

    知己知彼方能百战不殆,在HBase群集的运行过程中,我们需要了解HBase实际情况下的读写内存使用,才能最大化的对配置做出最加的调整,接下来说下如何查询HBase运行中读写内存使用情况

    Jmx查询

    http://xxxxxxxx.hadoop.db.com:11111/jmx?qry=Hadoop:service=HBase,name=RegionServer,sub=Server

    memStoreSize代表RegionServer中所有HRegion中的memstore大小的总和,单位是Byte。该值的变化,可以反应出一个RegionServer上写请求的负载状况,可以观察memstoreSize的变化率,如果在单位时间内变化比较抖动,可以近似认为写操作频繁。

    blockCacheFree代表block cache中空闲的内存大小。计算方法为:getMaxSize() – getCurrentSize(),单位是Byte,该值反映出当前BlockCache中还有多少空间可以被利用。

    blockCacheSize代表当前使用的blockCache的大小。BlockCache. getCurrentSize(),单位是Byte,该值反映出BlockCache的使用状况。

    以单台region server配置为例































    配置项配置值内存分配值实际使用量
    HBASE_REGIONSERVER_OPTS-Xms75g –Xmx75g75g75g
    hbase.regionserver.global.memstore.size0.2280g*0.22 = 17.6g10800044400/1024/1024/1024 ≈ 10G
    hfile.block.cache.size0.2280g*0.22 = 17.6g16763937528 /1024/1024/1024 ≈ 15.6G
    952802568 /1024/1024/1024 ≈ 0.9G

    结合单台regionserver 的配置来看,读写缓存都有一定空闲空间,这种情况下可以降低heap size来减少gc的次数和时长,然后我们还需要以群集所有region server的数据来判断该集群的配置是否合理,如果存在读写不均衡和热点情况都会影响不同region间的缓存大小。


    Memstore 深度解析



    • Memstore简介

    一张数据表由一个或者多个region 组成,在单个region中每个columnfamily组成一个store,在每个store中由一个memstore和多个storefile组成,如下图所示

    HBase是基于LSM-Tree数据结构的,为了提升写入性能,所有数据写入操作都会先写入memstore中(同时会顺序写入WAL),达到指定大小后会对memstore中的数据做次排序后在批量flush磁盘中,此外新写入的数据有较大概率被读取到,因此HBase在读取数据时首先检查memstore中是否有数据缓存,未命中的情况下再去找读缓存,可见memstore无论对于HBase的写入和读取性能都至关重要,而其中memstore flush操作又是memstore最核心的操作。



    • Memstore Flush操作










































    操作级别触发条件影响度
    memstore级别当region中任意一个memstore的大小达到了上限
    即>hbase.hregion.memstore.flush.size = 256mb
    小,短暂阻塞写
    region级别当region中所有的memstore的大小达到了上限
    即>hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size = 8 * 256mb
    小,短暂阻塞写
    regionserver级别当一个regionserver中所有memstore的大小达到了上限
    即> hbase.regionserver.global.memstore.size * heap_size = 0.22*75g
    大,阻塞regionserver上的所有写请求且时间较长
    regionserver中WAL Log数量达到上限> hbase.regionserver.maxlogs = 256
    系统会选取最早的一个 WAL Log对应的一个或多个region进行flush
    小,短暂阻塞写
    定期刷新> hbase.regionserver.optiOnalcacheflushinterval= 3600000小,短暂阻塞写
    手动刷新用户可以通过shell命令flush table 或者flush region name分别对一个表或者一个region进行flush小,短暂阻塞写


    • Memstore设置总结

    从memstore flush的动作来看,对业务影响最大是regionserver级别的flush操作,假设每个memstore大小为256mb,每个region有两个cf,整个regionserver上有100个region,根据计算可知,总消耗内存 = 256mb2100 = 51.2g >> 0.40*80g = 32g ,很显然这样的设置情况下,很容易触发region server级别的flush操作,对用户影响较大。

    根据如上分析,memstore的设置大小不仅取决于读写的比例,也要根据业务的region数量合理分配memstore大小,同样的我们对每台regionserver上region的数量及每张表cf的数量上的控制也能达到理想的效果。


    堆外内存注意事项


    Bucketcache的三种工作模式



    • heap

    heap模式分配内存会调用byteBuffer.allocate方法,从JVM提供的heap区分配。

    内存分配时heap模式需要首先从操作系统分配内存再拷贝到JVM heap,相比offheap直接从操作系统分配内存更耗时,但反之读取缓存时heap模式可以从JVM heap中直接读取比较快。



    • offheap

    offheap模式会调用byteBuffer.allocateDirect方法,直接从操作系统分配,因为内存属于操作系统,所以基本不会产生CMS GC,也就在任何情况下都不会因为内存碎片导致触发Full GC。

    内存分配时offheap直接从操作系统分配内存比较快,但反之读取时offheap模式需要首先从操作系统拷贝到JVM heap再读取,比较费时。



    • file

    file使用Fussion-IO或者SSD等作为存储介质,相比昂贵的内存,这样可以提供更大的存储容量。


    堆外内存的优势

    使用堆外内存,可以将大部分BlockCache读缓存迁入BucketCache,减少jvm heap的size,可以减少GC发生的频次及每次GC时的耗时

    BucketCache没有使用JVM 内存管理算法来管理缓存,而是自己对内存进行管理,因此其本身不会因为出现大量碎片导致Full GC的情况发生。


    堆外内存的缺陷

    读取data block时,需要将off heap的内存块拷贝到jvm heap在读取,比较费时,对读性能敏感用户不太合适。


    堆外内存使用总结

    对于读多写少且对读性能要求不高的业务场景,offheap模式能够有效的减少gc带来的影响,线上的vac集群在开启offheap模式后,GC频次和耗时都能有效降低,但是因为bucketcache 读的性能的问题达不到要求而回退到heap模式。


    JVM的配置优化及详解

    Hbase服务是基于JVM的,其中对服务可用性最大的挑战是jvm执行full gc操作,此时会导致jvm暂停服务,这个时候,hbase上面所有的读写操作将会被客户端归入队列中排队,一直等到jvm完成gc操作, 服务在遇到full gc操作时会有如下影响



    • hbase服务长时间暂停会导致客户端操作超时,操作请求处理异常。

    • 服务端超时会导致region信息上报异常丢失心跳,会被zk标记为宕机,导致regionserver即便响应恢复之后,也会因为查询zk上自己的状态后自杀,此时hmaster 会将该regionserver上的所有region移动到其他regionserver上

    如何避免和预防GC超时的不良影响,我们需要对JVM的参数进行优化

    hbase-env.sh























    配置项重要参数详解
    export HBASE_HEAPSIZE=4096HBase 所有实例包括Master和RegionServer占用内存的大小,不过一般用Master和RegionServer专有参数来分别设定他们的内存大小,推荐值给到4096
    export HBASE_MASTER_OPTS=" -Xms8g -Xmx8g -Xmn1g
    -XX:+UseParNewGC
    -XX:+UseConcMarkSweepGC
    -XX:CMSInitiatingOccupancyFraction=70"
    Master专有的启动参数,Xms、Xmx、Xmn分别对应初始堆、最大堆及新生代大小
    Master小堆,新生代用并行回收器、老年代用并发回收器,另外配置了CMSInitiatingOccupancyFraction,当老年代内存使用率超过70%就开始执行CMS GC,减少GC时间,Master任务比较轻,一般设置4g、8g左右,具体按照群集大小评估
    export HBASE_REGIONSERVER_OPTS="-XX:+UseG1GC
    -Xms75g –Xmx75g
    -XX:InitiatingHeapOccupancyPercent=83
    -XX:G1HeapRegiOnSize=32M
    -XX:ParallelGCThreads=28
    -XX:COncGCThreads=20
    -XX:+UnlockExperimentalVMOptions
    -XX:G1NewSizePercent=8
    -XX:G1HeapWastePercent=10
    -XX:MaxGCPauseMillis=80
    -XX:G1MixedGCCountTarget=16
    -XX:MaxTenuringThreshold=1
    -XX:G1OldCSetRegiOnThresholdPercent=8
    -XX:+ParallelRefProcEnabled
    -XX:-ResizePLAB
    -XX:+PerfDisableSharedMem
    -XX:-OmitStackTraceInFastThrow
    -XX:+PrintFlagsFinal
    -verbose:gc
    -XX:+PrintGC
    -XX:+PrintGCTimeStamps
    -XX:+PrintGCDateStamps
    -XX:+PrintAdaptiveSizePolicy
    -XX:+PrintGCDetails
    -XX:+PrintGCApplicationStoppedTime
    -XX:+PrintTenuringDistribution
    -XX:+PrintReferenceGC
    -XX:+UseGCLogFileRotation
    -XX:NumberOfGCLogFiles=5
    -XX:GCLogFileSize=100M
    Xloggc:${HBASE_LOG_DIR}/gc-regionserver$(hostname)-`date +'%Y%m%d%H%M'`.log
    -Dcom.sun.management.jmxremote.port=10102
    $HBASE_JMX_BASE"
    RegionServer专有的启动参数,RegionServer大堆,采用G1回收器,G1会把堆内存划分为多个Region,对各个Region进行单独的GC,最大限度避免Full GC及其影响

    初始堆及最大堆设置为最大物理内存的2/3,128G/3*2 ≈80G,在某些度写缓存比较小的集群,可以近一步缩小。

    InitiatingHeapOccupancyPercent代表了堆占用了多少比例的时候触发MixGC,默认占用率是整个 Java 堆的45%,改参数的设定取决于IHOP > MemstoreSize%+WriteCache%+10~20%,避免过早的MixedGC中,有大量数据进来导致Full GC

    G1HeapRegionSize 堆中每个region的大小,取值范围【1M..32M】2^n,目标是根据最小的 Java 堆大小划分出约 2048 个区域,即heap size / G1HeapRegiOnSize= 2048 regions

    ParallelGCThreads设置垃圾收集器并行阶段的线程数量,STW阶段工作的GC线程数,8+(logical processors-8)(5/8)

    ConcGCThreads并发垃圾收集器使用的线程数量,非STW期间的GC线程数,可以尝试调大些,能更快的完成GC,避免进入STW阶段,但是这也使应用所占的线程数减少,会对吞吐量有一定影响

    G1NewSizePercent新生代占堆的最小比例,增加新生代大小会增加GC次数,但是会减少GC的时间,建议设置5/8对应负载normal/heavy集群

    G1HeapWastePercent触发Mixed GC的堆垃圾占比,默认值5
    G1MixedGCCountTarget一个周期内触发Mixed GC最大次数,默认值8
    这两个参数互为增加到10/16,可以有效的减少1S+ Mixed GC STW times

    MaxGCPauseMillis 垃圾回收的最长暂停时间,默认200ms,如果GC时间超长,那么会逐渐减少GC时回收的区域,以此来靠近此阈值,一般来说,按照群集的重要性 50/80/200来设置

    verbose:gc在日志中输出GC情况



    推荐阅读
    • 在搭建Hadoop集群以处理大规模数据存储和频繁读取需求的过程中,经常会遇到各种配置难题。本文总结了作者在实际部署中遇到的典型问题,并提供了详细的解决方案,帮助读者避免常见的配置陷阱。通过这些经验分享,希望读者能够更加顺利地完成Hadoop集群的搭建和配置。 ... [详细]
    • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
      本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
    • JVM参数设置与命令行工具详解
      JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。 ... [详细]
    • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
    • 浅析python实现布隆过滤器及Redis中的缓存穿透原理_python
      本文带你了解了位图的实现,布隆过滤器的原理及Python中的使用,以及布隆过滤器如何应对Redis中的缓存穿透,相信你对布隆过滤 ... [详细]
    • JUC(三):深入解析AQS
      本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
    • com.sun.javadoc.PackageDoc.exceptions()方法的使用及代码示例 ... [详细]
    • Java高并发与多线程(二):线程的实现方式详解
      本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
    • 深入解析Struts、Spring与Hibernate三大框架的面试要点与技巧 ... [详细]
    • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
    • Hadoop平台警告解决:无法加载本机Hadoop库的全面应对方案
      本文探讨了在Hadoop平台上遇到“无法加载本机Hadoop库”警告的多种解决方案。首先,通过修改日志配置文件来忽略该警告,这一方法被证明是有效的。其次,尝试指定本地库的路径,但未能解决问题。接着,尝试不使用Hadoop本地库,同样没有效果。然后,通过替换现有的Hadoop本地库,成功解决了问题。最后,根据Hadoop的源代码自行编译本地库,也达到了预期的效果。以上方法适用于macOS系统。 ... [详细]
    • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
      开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
    • 如何利用Java 5 Executor框架高效构建和管理线程池
      Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
    • 在处理大图片时,PHP 常常会遇到内存溢出的问题。为了避免这种情况,建议避免使用 `setImageBitmap`、`setImageResource` 或 `BitmapFactory.decodeResource` 等方法直接加载大图。这些函数在处理大图片时会消耗大量内存,导致应用崩溃。推荐采用分块处理、图像压缩和缓存机制等策略,以优化内存使用并提高处理效率。此外,可以考虑使用第三方库如 ImageMagick 或 GD 库来处理大图片,这些库提供了更高效的内存管理和图像处理功能。 ... [详细]
    • Hadoop 2.6 主要由 HDFS 和 YARN 两大部分组成,其中 YARN 包含了运行在 ResourceManager 的 JVM 中的组件以及在 NodeManager 中运行的部分。本文深入探讨了 Hadoop 2.6 日志文件的解析方法,并详细介绍了 MapReduce 日志管理的最佳实践,旨在帮助用户更好地理解和优化日志处理流程,提高系统运维效率。 ... [详细]
    author-avatar
    115路公交车_984
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有