网易视频云:HBase最佳实践-CMS GC调优_第1页
网易视频云:HBase最佳实践-CMS GC调优_第2页
网易视频云:HBase最佳实践-CMS GC调优_第3页
网易视频云:HBase最佳实践-CMS GC调优_第4页
网易视频云:HBase最佳实践-CMS GC调优_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、网易视频云:HBase最佳实践CMS GC调优网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,为客户提供稳定流畅、低时延、高并发的视频直播、录制、存储、转码及点播等音视频的PaaS服务。在线教育、远程医疗、娱乐秀场、在线金融等各行业及企业用户只需经过简单的开发即可打造在在线音视频平台。HBase发展到当下,对其进行的各种优化从未停止,而GC优化更是其中的重中之重。从0.94版本提出MemStoreLAB策略、Memstore Chuck Pool策略对写缓存Memstore进行优化开始,到0.96版本提出BucketCache以及堆外内存方案对读缓存BlockC

2、ache进行优化,再到后续2.0版本宣称会引入更多堆外内存,可见HBase会将堆外内存的使用作为优化GC的一个战略方向。然而无论引入多少堆外内存,都无法避免读写全路径使用JVM内存,就拿BucketCache中offheap模式来讲,即使HBase数据块是缓存在堆外内存的,但是在读取的时候还是会首先将堆外内存中的block加载到JVM内存中,再返回给用户。可见,无论使用多少堆外内存,对JVM内存的使用终究是绕不过去,既然绕不过去,就还是需要落脚于GC本身,对GC本身进行优化。本文就将会介绍HBase应用场景下CMS GC策略的调优技巧,后续还会针对另一业界开始使用的GC策略G1GC策略在HBa

3、se应用场景下进行调优介绍。 CMS GC工作原理如果看官已经对CMS GC工作原理比较熟悉,完全可以跳过本节内容,直接进入下节。如果看官还对CMS GC不是很了解,可以参考笔者之前的另一篇文章HBase GC的前生今生-身世篇,文中对JVM的内存结构以及CMS GC进行了相当详细的介绍。为了下文介绍方便,在此还是对其中的一些重要知识点进行提炼: 1. 整个JVM内存由Young区、Tenured区和Perm区三部分组成,其中Young区又分为一个Eden区和两个Survivor区 2. 整个对象生命周期简要说明(一定要烂熟于心,下文会一直用到): (1)Young区:一个对象初始化之后,首先

4、会进入Eden区,当Eden区满之后会触发一次Minor GC,Minor GC会检查Eden区所有对象是否依旧存活(是否有其他对象引用),如果存活,会将其从Eden区拷贝到Survivor区,并将这些存活对象的age加一,而死亡的对象会被作为垃圾回收。此时Eden区又空闲出来,等新对象填充,填充满之后再会触发Minor GC,如此往复。需要注意的是,每执行一次Minor GC,存活对象的age就会加一。 (2)Tenured区:一旦存活对象的age超多一定阈值就会晋升到Tenured区,因此可以理解为Tenured区一般存放长寿对象。很显然,随着时间流逝,Tenured区也会被填充满,此时就

5、会触发CMS GC(old gc),这种GC相对比较复杂,由5个步骤组成,详见参考文章。 3. 无论是Minor GC还是CMS GC,都会Stop-The-World,即停止用户的一切线程,只留下gc线程回收垃圾对象。其中Minor GC的STW时间主要耗费在复制阶段,CMS GC的STW时间主要耗费在标示垃圾对象阶段。 GC调优目标上节简单介绍了Java虚拟机的内存结构以及Java GC的基本知识,接下来会在此基础上介绍HBase集群中GC的几种参数调优技巧。在介绍具体的调优技巧之前,有必要先来看看GC调优的最终目标和基本原则: 1. 平均Minor GC时间尽可能短。因为整个Minor

6、GC都处于STW,因此短时间Minor GC会使用户读写更加平稳,延迟可控。 2. CMS GC次数越少越好。时间越短越好。一方面是因为一次CMS GC一般都会引起至少秒级的应用暂停,对用户读写影响较大;另一方面频繁的CMS GC会产生大量的内存碎片,严重的时候会引起Full GC,导致RegionServer宕机。 下面对参数的调优技巧都谨遵以上原则,尤其对于HBase这类延迟敏感性项目而言,在尽量避免严重影响用户读写的情况下使得GC更加平稳、暂停时间更短! CMS GC优化技巧本节会针对HBase这一应用场景对JVM的各种GC参数进行分析,主要分三个阶段进行。第一阶段会介绍适用于所有场景下

7、的GC参数配置,这些参数不需要太多解释读者就可以轻松理解;第二阶段和第三阶段分别就两组参数进行调优讲解,这两组参数一般会根据不同的应用场景进行设置才能使得GC效果最好,鉴于这两组参数的复杂性,我们会通过理论实验的方式一一进行说明; 阶段一:默认推荐配置在介绍具体的调优技巧之前,先来看看CMS GC涉及到的所有相关参数及其对应的意义,下面是最常见的参数: -Xmx -Xms -Xmn -Xss -XX:MaxPermSize= M -XX:+SurvivorRatio=S -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemar

8、kEnabled -XX:+MaxTenuringThreshold=N -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=C -XX:-DisableExplicitGC通过上文对各个GC参数的说明,可以轻松得出第一阶段推荐的参数设置如下,这样的设置基本适用于所有的场景: -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMS

9、CompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75% -XX:-DisableExplicitGC调优预准备上文通过解释各个GC参数意义给出了基本的推荐设置,同时也提到几个对性能影响重大的参数:Xmn、SurvivorRatio以及MaxTenuringThreshold,下面会通过理论推理实验验证的方式对这几个参数在HBase系统的设置进行调优。在深入介绍调优技巧之前,需要额外针对三个相关部分预先做下讲解,这样可以更好地理解下文的实验数据分析。这三部分

10、分别是:测试环境测试基本条件,GC日志解释,HBase场景内存分析; 测试环境首先就下文中实验测试的硬件拓扑、软件配置以及相关测试数据情况进行说明: 需要强调的是HBase全部配置为BucketCache模式,而不是LruBlockCache。使用了大量堆外内存作为读缓存,在很大程度上优化了GC,如下图: 上图是在两种缓存策略下GC表现情况,可见BucketCache模式比LruBlockCache模式GC表现好很多,强烈建议线上配置BucketCache模式。可能很多童鞋都测试过这两种模式下的GC、吞吐量、读写延迟等指标,看到测试结果都会很疑惑,BucketCache模式下的各项性能指标都比

11、LruBlockCache差了好多,笔者也疑惑过,后来才明白:测试肯定是在基本全内存场景下进行的,这种情况下确实会是如此。读者可以想想为什么会如此,实在不明白可以参考之前一篇博文BlockCache方案性能对比测试报告。但是话又说回来,在大数据场景下又有多少业务会是全内存操作呢? GC日志分析介绍完实验基本条件后,再对GC日志进行简单的解释,方便下文对日志进行分析。需要注意只有在添加参数-XX:+PrintTenuringDistribution才能打印对应日志,强烈建议线上集群开启该参数,日志片段如下: 2016-07-26T10:37:16.933+0800: 227753.150: GC

12、2016-07-26T10:37:16.933+0800: 227753.150: ParNewDesired survivor size 268435456 bytes, new threshold 5 (max 15)- age 1: 57523184 bytes, 57523184 total- age 2: 80236520 bytes, 137759704 total- age 3: 73226496 bytes, 210986200 total- age 4: 50318392 bytes, 261304592 total- age 5: 63166384 bytes, 32447

13、0976 total- age 6: 240 bytes, 324471216 total: 1268903K->305311K(1572864K), 0.0840620 secs 26598675K->25635082K(66584576K), 0.0844700 secs Times: user=1.82 sys=0.08, real=0.08 secs上述日志片段分三部分进行解释: 第一部分:基本信息区,主要有两点需要重点关注,其一是Desired survivor size 268435456 bytes,表示Survivor区大小为

14、256M;其二是new threshold 5 (max 15),表示对象晋级老生代的最大阈值为15,但是因为Survivor区太小导致age大于5的对象会直接溢出晋级老生代(也有可能是阈值设置太大)。 第二部分:不同age对象分布区,第一列表示该Young区共分布有age在16的对象;第二列表示所在age含有的对象集所占内存大小,比如age为2的所有对象总大小为80236520 bytes;第三列表示小于对应age的所有对象占用内存的累加值,比如age2对应第二列137759704 total表示age为1和age为2的所有对象总大

15、小; 第三部分:内存回收信息区,第一列表示Young区的内存回收情况,1268903K->305311K表示Young区回收前内存为1268903K,回收后变为305311K;第二列表示Jvm Heap的内存回收情况,26598675K->25635082K(66584576K) 表示当前Jvm总分配内存为66584576K,回收前对象占用内存为26598675K,回收后对象占用内存为25635082K;第三列表示回收时间,其中real表示本次gc所消耗的STW时间,即用户业务暂停时间。 HBase场景内存分析通常来讲,每种应用都会有自己的内存对象特性,分类来说无非就两种:一种是短

16、寿对象(指存活对象较短的对象,比如临时变量等)居多工程,比如大多数纯HTTP请求处理工程,短寿对象可能占到所有对象的70%左右;另一种是长寿对象(指存活对象较长的对象,比如TTL设置较长的缓存对象)居多工程,比如类似于HBase、Spark等这类大内存工程。具体以HBase为例,来看看具体的内存对象: 1. RPC请求对象,比如Request对象和Response对象,一般这些对象会随着短连接RPC的销毁而消亡,这些对象可以认为是短寿对象; 2. Memstore对象,HBase中Memstore中对象一般会持续存活较长时间,用户写入数据到Memstore中之后对象就一直存在,直至Memsto

17、re写满之后flush到HDFS。一般在写入QPS较高的情况下写满memstore也通常需要一个小时左右,可见Memstore对象肯定是长寿对象。另外,Memstore对象默认比较大,2M大小。 3. BlockCache对象,和Memstore对象一样,BlockCache对象一般也会在内存存活较长时间,属于长寿对象。这种对象默认64K大小。 因此可以看出,HBase系统属于长寿对象居多的工程,因此GC的时候只需要将RPC这类短寿对象在Young区淘汰掉就可以达到最好的GC效果。 阶段二:NewParSize调优理论分析NewParSize表示young区大小,而young区大小直接决定mi

18、nor gc的频率。minor gc频率一方面决定单次minor gc的时间长短,gc越频繁,gc时间就越短;一方面决定对象晋升到老年代的量,gc越频繁,晋升到老年代的对象量就越大。解释起来就是: 1. 增大young区大小,minor gc频率降低,单次gc时间会较长(young区设置更大,一次gc就需要复制更多对象,耗时必然比较长),业务读写操作延迟抖动较大。反之,业务读写操作延迟抖动较小,比较平稳。 2. 减小young区大小,minor gc频率增快,但会加快晋升到老年代的对象总量(每gc一次,对象age就会加一,当age超过阈值就会晋升到老年代,因此gc频率越高,age就增加越快),

19、潜在增加old gc风险。 因此设置NewParSize需要进行一定的平衡,不能设置太大,也不能设置太小。 实验结果实验条件:分为独立对照试验,三台RegionServer分别设置Xmn为512m、2g、5g,Xmn越大,分配的Young区越大;SurvivorRatio和MaxTenuringThreshold取默认值; 实验结果曲线图: 结果分析1. 图一是Xmn不同场景下总体的GC耗时曲线图,其中横坐标表示GC次数,纵坐标表示GC耗时(STW),单位ms。需要特别说明的是,这3条曲线是在相同时间段统计的,也就是说在这段时间内Xmn为512m的情况下GC次数最多,而相应的Xmn为5的情况下

20、GC次数最少。 2. 图一整体上来看绿线尖峰很多而且很高,表示CMS GC较频繁,但绿线主体部分处于红线与蓝线之下,表示平均Minor GC耗时更短;蓝线GC次数最少,尖峰也比较突出,另外Minor GC相比红线和绿线耗时更长;红线的Minor GC耗时介于蓝线和绿线之间,尖峰比较平稳,表示CMS GC相对比较短暂;因此总体来看,红线代表的Xmn为2的场景下CMS GC更加合理,平均Minor GC相对不高,而相比之下,另外两种场景都有特别明显的缺陷,Xmn2是一个最优的选择;图一只能直观上看出这么多,更加精确结果需要接着看图二和图三。 3. 图二主要统计Minor GC的主要指标:总GC次数

21、以及平均单次Minor GC耗时。两者来看,更关注后者,因为后者决定了业务读写的延迟以及稳定度;由图中可以看出,Xmn512m的平均单次Minor GC耗时最少,其次是Xmn2g,最差是Xmn5g,达到了130ms左右,意味着在其Minor GC过程中所有业务读写延迟至少为130ms;这个也很好理解,Young区越小,Minor GC频率越高,单次Minor GC需要复制的对象数就越少,耗时越少; 4. 图三主要统计CMS GC(老年代GC)的主要指标:CMS GC次数以及平均单次老年代GC耗时(只算STW耗时);由图中可以看出,Xmn2g无论是GC次数还是GC耗时都更加优秀,相比之下Xmn5

22、12m就是最差的选择;解释起来也很简单,因为Young区设置太小,Minor GC频率高,对象age增加很快,很多对象就有可能因为age超过阈值(默认6)晋升到老年代,相对而言会更有可能引入大量短寿对象晋升老年代。而短寿对象相对而言会比较小,比如request、response等,大量小对象一旦进入老年代,就会导致CMS GC的时候需要标注更多对象,必然比较耗时; 实验结论可见,测试结果基本和理论分析一致,Xmn设置过小会导致CMS GC性能较差,而设置过大会导致Minor GC性能较差,因此建议在JVM Heap为64g以上的情况下设置Xmn在13g之间,在32g之下设置为512m1g;具体

23、最好经过简单的线上调试;需要特别强调的是,笔者在很多场合都看到很多HBase线上集群会把Xmn设置的很大,比如有些集群Xmx为48g,Xmn为10g,查看日志发现GC性能极差:单次Minor GC基本都在300ms500ms之间,CMS GC更是很多超过1s。在此强烈建议,将Xmn调大对GC(无论Minor GC还是CMS GC)没有任何好处,不要设置太大。 阶段三:增大Survivor区大小(减小SurvivorRatio) & 增大MaxTenuringThreshold理论分析上文讲过,一次Minor GC会将存活对象从Eden区(以及survivor from区)复制到Surv

24、ivor区(to区),因此增大Survivor区可以容纳更多的存活对象。这样就会防止因为Survivor区太小导致很对存活对象还没有达到MaxTenuringThreshold阈值就直接进入老生代,潜在增大old gc的触发频率;但是Survivor区设置太大也会有一定的问题,Survivor设置较大会使得对象可以在Young区待的时间很长,但是对于一些长寿对象较多的场景下(比如HBase),大量长寿对象长时间待在Young区做很多无谓的复制,一定程度上增加Minor GC开销。 另外,增加MaxTenuringThreshold相当于提高了进入老年代的门槛,可以有效限制进入老年代的对象数。和

25、Survivor设置相似,调整MaxTenuringThreshold也需要做一个取舍,设置太小会增加CMS GC的触发频率以及耗时,而设置太大则会在长寿对象较多场景下增加Minor GC开销。一般情况下,默认MaxTenuringThreshold=15已经相对比较大,不需要做任何调整。 实验结果实验条件:分为独立对照试验,三台RegionServer分别设置SurvivorRatio为2、8、15,SurvivorRatio越大,Survivor区大小越小;MaxTenuringThreshold取默认值;其他:-Xmx64g,-Xmn2g; 实验结果曲线: 结果分析1. 图一是Survi

26、vorRatio在三种不同场景下对应的GC性能曲线图,大体可以看出蓝线Minor GC次数最多,绿线尖峰太多,即CMS GC性能最差;具体细节再来看图二和图三。 2. 图二主要统计Minor GC主要指标:平均单次Minor GC耗时三者基本相当,SurvivorRatio:2场景下稍微较高,这是因为SurvivorRatio=2对应的Survivor区较大,可以使得对象在Young区待的时间很长,在HBase这种长寿对象较多的情况下,可能会增加一些无谓的复制开销(下文会通过日志分析详细解释)。另外,SurvivorRatio=2场景下Minor GC频率也比较高,可能的原因是因为在总Youn

27、g大小确定的情况下,Survivor越大,Eden自然越小,Minor GC频率就会增大。可见,SurvivorRatio=2场景下Minor GC性能相对稍微较差。 3. 图三主要统计CMS GC主要指标:三者CMS GC次数基本相当,SurvivorRatio=2场景下单次CMS GC耗时最少,相比SurvivorRatio=8的场景耗时减少30%左右,性能最好;而相比之下SurvivorRatio=15场景下耗时最长,性能相当差;这是因为SurvivorRatio=2场景下存活对象可以长时间待在Young区,可以得到充分的淘汰,晋升到老生代的短寿小对象会比较少,因而CMS GC性能较好;相比SurvivorRatio=15会因为Survivor区设置太小,很多短寿小对象因为得不到充分

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论