诡异的超长时间GC问题定位

HBase的GC策略采用PawNew+CMS, 这是大众化的配置,ParNew经常会出现停顿时间特别长的情况,有时候甚至长到令人发指的地步,例如请看如下日志:

2012-10-17T05:54:54.293+0800: 739594.224: [GC 739606.508: [ParNew: 996800K->110720K(996800K), 178.8826900 secs] 3700515K->2985396K(6180736K), 187.4174260 secs] [Times: user=1.70 sys=2.42, real=191.35 secs] 

不要慌,因为我也没见过这么长的GC,既然GC这么长,直接导致的问题就是HBase连接ZK的session超时,而HBase在rs超时的情况下,会让自己挂掉(这样处理显然也是合理的)。关于session可以参看另外两篇博文,http://crazyjvm.iteye.com/blog/1701032http://crazyjvm.iteye.com/blog/1693757

另外要补充的是,在这台服务器上还运行着hadoop和redis, 这两个应用都狂吃内存,所以第一反应就是因为swap导致了这个问题,对swap不太了解的可以参看https://www.linux.com/news/software/applications/8208-all-about-linux-swap-space/,我看了下我们的swappiness的值是60,总共可用swap空间是32G多!那么事情就是这么发生了,我们会定时的向HDFS上插数据,数据量不小,这个时候Linux就会使用buffer把write的数据给缓存起来,另一方面,redis也会定期的灌数据(10G+),这样buffer肯定就不小了,当然读的操作也会不少,那么Cache使用起来也很厉害(当然,比buffer猛多了),虽然说这么空间不是真正的算在内存使用里面,但是它却会导致swap的发生,它让那些在内存中的部分未使用数据swap进硬盘了,对了,别忘了,这台服务器上还有hadoop哦,火力全开的跑job,内存火箭般的升上去了,我看了下hbase进程,swap出去的内存基本都50%以上了,那内存回收的时候能快吗?

再解释下,为什么ParNew的时候慢,而CMS的时候基本没事呢。熟悉GC的同学应该瞬间就想到了,ParNew采用的是Copy算法,它要把eden以及一个survivor区域中的存活对象复制到另外一个survivor区域中,这样就相当于GC时要对硬盘进行随机读写的行为了,能快吗?另一方面(这点我不确定,可能没啥问题),CPU在那个时刻使用率极高,影响了回收线程的工作(不过应该没啥问题)。 说说CMS,CMS采用的是MARK-SWEEP算法,它只管标记和删除,不用复制,更重要的是,在逻辑上,Old Gen的大多数对象仍然在内存中,显然会好很多,至于COMPACT的步骤就在CMS失败的情况下由Parallel Old收集器来做了,这个收集器是MARK-COMPACT算法。当然了,UseCMSCompactAtFullCollection和CMSFullGCsBeforeCompaction有助你结合CMS完成COMPACT的过程。

 

SWAP影响这么大的原因有几点,我们先不去看置换算法之类的影响,最大头的寻道时间和旋转延迟时间就说明问题了,如果读磁盘上分散的很厉害的数据,那么效率肯定非常低,因为每次都需要重新寻道,并且加上旋转延迟。如果数据全部在一起,是连续的,那么磁盘的表现是相当厉害的,这一点也正是hadoop的基础。(擦!字体怎么变不了 ?)

 

 

对GC不熟悉的同学肯定需要好好地去补下了,使用JVM平台不熟悉GC,说不过去。如果在运行过程中有另外的发现,再补上吧。

你可能感兴趣的:(jvm,cms,GC,hbase,swap)