众所周知ES的java heap通常设置为32G以下,因为大于某个阈值(根据系统不同而不同,根据oracle官网https://docs.oracle.com/javase/8/docs/technotes/guides/vm/performance-enhancements-7.html#zeroBasedCompressedOop最小可到26G),Zero-Based Compressed Ordinary Object Pointers (oops)不会被启用,将会导致更多的内存消耗。
现场的情况ES集群都使用的是CMS垃圾回收,heap设置为31G,有些机器没有任何任务的情况下,也会出现6-7秒进行一次gc,由于heap比较大,一次minor gc的消耗通常在200ms左右,在出现大量请求的时候,gc的时间就很长了,这是不能容忍的。后来现场改用G1 GC解决了这个问题。
还有出现的情况是,es存储的index过多,导致old gen满了,full gc都无法回收的情况,特别当其是G1 GC时这个情况更为严重,更容易导致内存溢出。因为es是要将index的倒排索引保存在java heap里的,且不会被回收,如果集群保存过多的open状态的index,很有可能会导致heap的老年代使用比例过高的问题。这个问题关闭掉部分不用的索引就可以了。