前文介绍了滴滴自研的ES强一致性多活是如何实现的,其中也提到为了提升查询性能和解决查询毛刺问题,滴滴ES原地升级JDK17和ZGC,在这个过程中我们遇到了哪些问题,怎样解决的,以及最终上线效果如何,这篇文章就带大家深入了解。
背景
滴滴ES在2020年的时候由2.X升级到7.6.0,该版本是在官方7.6.0的基础上改造而来,支持的是JDK11,采用的垃圾回收器是G1。ES的业务主要分为两类,一类是日志场景,该场景写多读少,高峰期CPU使用率在85%左右,写入性能是它的主要瓶颈;另一类是非日志场景,例如POI检索、订单、支付,这些场景对查询耗时及查询稳定性都有着较高的要求。
随着ES业务数据量的增长,GC导致的查询稳定性压力剧增,已经逐渐无法满足业务需求。以下是ES面临的主要问题:
非日志场景的GC问题
1、Yong GC平均暂停时间长,一些集群的平均暂停时间达到百毫秒级别。
GC暂停时间长在订单集群这种112G大内存的进程中表现尤为明显。下图为订单集群的GC暂停时间,可以发现一次Yang GC的平均暂停时间就达到了200ms,有些甚至超过了1s。ES的核心业务POI、订单等对查询耗时的P99以及Max都有一定的需求,GC暂停导致的查询延时以及毛刺问题无法满足业务需求。
订单集群的GC暂停时间
2、Full GC问题频繁,影响集群稳定性。
G1的Full GC会导致GC模式退化为串行扫描整个堆,导致几十秒甚至是分钟级别的暂停。这种长时间的暂停不仅影响用户的查询,还容易造成节点间的通信超时,导致master、dataNode脱离集群,影响集群稳定性。
3、JDK11-G1内存不回收问题频发,如下图所示,通过调优G1参数也没有很好地解决内存问题。
GC不回收现象
日志场景的Reject问题
ES的日志场景写入量大,GC频繁且性能较差,这也进一步加剧日志集群的写入Reject问题。
JDK17落地
2022年上半年,ES开启了扫雷专项,意在打造一个更高性能、更低延迟、更加稳定的ES检索引擎。在这种背景下,对JDK17-ZGC进行调研,经过测试ZGC可以将GC暂停时间控制在10ms内,能够很好地解决GC导致的查询耗时问题。
同时针对日志这种高吞吐场景,测试了JDK17-G1,发现GC性能相较于JDK11-G1提升了15%,并且JDK17在向量化支持、字符串处理等方面做了许多优化,能在一定程度上缓解日志集群的写入压力。如图所示:
官方GC吞吐性能
官方GC延迟
生产环境需要稳定、可维护并且免费的JDK版本,同时JDK17是JDK11后又一个可长期支持的版本,在性能、稳定性和安全性上都有很大的提升,对ZGC的适配也进一步加强,对G1的稳定性和性能有极大的提升。因此,选择了这一版本。
ZGC 是一个并发的、单代的、基于区域的、NUMA 感知的