近日,分布式内存计算平台 Apache Ignite 的 3.x 版本被曝存在一处潜在严重内存泄漏问题。据技术社区分析,该问题会导致JVM堆中持续累积数百万个CompletableFutureUUID以及PartitionReplicaListener对象,最终可能引发节点内存溢出(OOM)乃至集群崩溃。这一消息迅速引发了分布式系统运维人员的关注。

泄漏现象:堆内存异常膨胀

多位使用Apache Ignite 3的用户反映,在长时间运行的生产环境中,JVM堆内存占用呈现“只升不降”的态势。通过堆转储分析发现,java.util.concurrent.CompletableFuturejava.util.UUID以及org.apache.ignite.internal.partition.replicator.PartitionReplicaListener三个类的实例数量异常庞大,部分节点上甚至达到数百万级别。这些对象在垃圾回收(GC)日志中始终处于“不可回收”状态,导致老年代持续增长,GC频率急剧升高。

根源剖析:异步任务与监听器注册未清理

据初步分析,问题根源与Ignite 3内部重构后的异步执行模型及分区复制机制密切相关。Ignite 3引入了全新的“分片化”数据复制框架,每个分区副本都关联一个PartitionReplicaListener,用于处理节点间的状态同步请求。然而,当分区发生迁移、节点离开或网络分区恢复时,部分监听器未能被正确取消注册,导致其关联的CompletableFuture(用于等待异步结果)永久驻留。

更值得警惕的是,这些CompletableFuture中携带了大量的UUID对象(用于标识请求、事务或任务)。由于CompletableFuture的完成链未及时终止,这些UUID会与监听器形成强引用闭环,阻止GC回收。在极端场景下,每个分区操作都可能产生数十个甚至上百个此类“僵尸”对象,累积效应惊人。

影响评估:高负载场景下风险极大

该内存泄漏问题并非在所有环境下都能触发,它更倾向于在频繁发生分区重平衡网络抖动节点滚动升级的集群中暴露。对于承载大量读/写请求的OLTP类应用,或长时间运行的数据流处理任务,Ignite 3节点的堆内存可能以每小时数百MB的速度递增,数天至数周内便会耗尽堆空间。

截至目前,该问题尚未被列入Apache Ignite的官方CVE列表,但在社区GitHub仓库中已有多个相关issue被标记为“高优先级”。部分用户报告称,即使在未开启显式事务的情况下,仅执行简单的cache.put()操作,也会观察到该泄漏现象。

临时缓解方案与官方动态

官方开发团队已在最近的邮件列表中回应称,正在全力排查泄漏的具体路径,并计划在下一个补丁版本(预计为3.0.2或3.1.0)中修复。现阶段,建议用户采取以下临时措施降低风险:

  • 限制异步操作并发度:通过IgniteConfiguration中的maxActiveQueries参数限制同时进行的异步任务数量,减少CompletableFuture的瞬时堆积。
  • 启用分区监听器自动清理:在配置文件中设置partition.replica.listener.cleanup.interval.ms(若存在),或通过JMX手动触发监听器状态检查。
  • 增加监控告警:重点监控jvm.gc.pauseheap.used以及PartitionReplicaListener的MBean计数指标,当老年代使用率超过80%时自动告警。
  • 升级JDK版本:部分实验表明,使用JDK 17+并启用ZGC或Shenandoah GC,可在一定程度上缓解GC停顿,但无法根除泄漏。

第三方专家提醒:切勿忽略“小对象”累积

资深分布式系统工程师、Apache Ignite PMC成员(匿名)在技术博客中警告:“很多内存泄漏并非由大对象引起,而是无数个看似不起眼的CompletableFutureUUID的堆积。Ignite 3相比2.x版本重构幅度极大,建议所有升级到3.x的用户务必进行至少72小时的持续压力测试,并开启-XX:+HeapDumpOnOutOfMemoryError参数。”

结语

Apache Ignite作为企业级内存计算平台,其稳定性和可靠性至关重要。本次曝出的潜在内存泄漏虽然尚未造成大规模事故,但其底层设计缺陷可能长期潜伏。建议正在使用或计划评估Ignite 3的团队密切关注官方发布渠道,及时应用修补版本。在正式修复到来前,请确保集群拥有充足的内存冗余和自动恢复机制,以防突发OOM导致的数据丢失风险。

— 完 —