You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

30个Ignite客户端连接单服务器引发BufferUnderflowException问题求助

问题描述

我们用30个Ignite客户端连接1台Ignite服务器,所有客户端都会创建多个缓存,任务完成后销毁缓存。销毁缓存时会触发分区映射交换(Partition Map Exchange),同时启动每个缓存的二进制元数据清理,这期间我们遇到了BufferUnderflowException,导致存储暂时不可用。

注:使用10个客户端时未出现该问题,现象出现在Ignite 2.17版本。

堆栈跟踪

Caused by: java.nio.BufferUnderflowException
    at java.base/java.nio.Buffer.nextGetIndex(Unknown Source)
    at java.base/java.nio.HeapByteBuffer.get(Unknown Source)
    at org.apache.ignite.internal.binary.streams.BinaryByteBufferInputStream.readByte(BinaryByteBufferInputStream.java:47)
    at org.apache.ignite.internal.binary.BinaryUtils.doReadStringArray(BinaryUtils.java:1428)
    at org.apache.ignite.internal.client.thin.TcpIgniteClient.lambda$cacheNames$8(TcpIgniteClient.java:248)
    at org.apache.ignite.internal.client.thin.TcpClientChannel.receive(TcpClientChannel.java:428)
    at org.apache.ignite.internal.client.thin.TcpClientChannel.service(TcpClientChannel.java:326)
    at org.apache.ignite.internal.client.thin.ReliableChannel.lambda$service$0(ReliableChannel.java:210)
    at org.apache.ignite.internal.client.thin.ReliableChannel.applyOnDefaultChannel(ReliableChannel.java:863)
    at org.apache.ignite.internal.client.thin.ReliableChannel.applyOnDefaultChannel(ReliableChannel.java:809)
    at org.apache.ignite.internal.client.thin.ReliableChannel.service(ReliableChannel.java:210)
    at org.apache.ignite.internal.client.thin.ReliableChannel.service(ReliableChannel.java:191)
    at org.apache.ignite.internal.client.thin.ReliableChannel.service(ReliableChannel.java:310)
    at org.apache.ignite.internal.client.thin.TcpIgniteClient.cacheNames(TcpIgniteClient.java:247)
    at ignite.client.ClientDatastoreInstance.exists(ClientDatastoreInstance.java:216)
解决办法

1. 升级Ignite版本

Ignite 2.17存在多并发场景下二进制元数据处理、缓存销毁竞态的已知bug,后续稳定版本(如2.18及以上)已修复此类问题。升级到最新稳定版是最彻底的解决方案。

2. 控制缓存销毁并发度

问题仅在30个客户端时出现,说明高并发销毁是核心诱因。可在客户端侧做限流:

  • 让客户端分批执行缓存销毁操作,避免同时触发大量分区交换和元数据清理
  • 用分布式锁控制销毁操作的并发量,确保同一时间只有少量客户端执行销毁

示例伪代码:

// 客户端通过分布式锁控制缓存销毁并发
IgniteLock destructionLock = igniteClient.lock("global-cache-destruction-lock");
destructionLock.lock();
try {
    igniteClient.cache("target-cache").destroy();
} finally {
    destructionLock.unlock();
}

3. 临时禁用自动元数据清理

通过JVM参数关闭自动二进制元数据清理,可避免清理过程中的竞态问题,但会导致元数据累积占用内存,仅作为应急临时方案:

-DIGNITE_BINARY_METADATA_CLEANUP_ENABLED=false

4. 调整分区交换超时参数

增大分区交换的超时时间,避免高并发下交换过程超时引发数据异常,在Ignite配置文件中修改:

<property name="exchangeTimeout" value="30000"/> <!-- 默认10秒,调整为30秒 -->

内容的提问来源于stack exchange,提问作者Rohan19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:38:17