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

Voldemort调用getAll()出现InsufficientOperationalNodesException问题求助

Voldemort getAll() 触发InsufficientOperationalNodesException 连接池耗尽问题排查与解决

问题现象

我们在调用voldeMortStoreClient.getAll()方法时,偶尔会触发异常。起初系统正常运行数日,之后每日出现少量该异常且频次逐渐增加,最终连接池内所有连接失效,所有请求均返回此异常:

  • 服务器版本:1.10.24
  • 集群规模:1

异常详情

voldemort.store.InsufficientOperationalNodesException: 1 get alls required, but 0 succeeded. Failing nodes : []
at voldemort.store.routed.action.PerformSerialGetAllRequests.execute(PerformSerialGetAllRequests.java:197)
at voldemort.store.routed.Pipeline.execute(Pipeline.java:212)
at voldemort.store.routed.PipelineRoutedStore.getAll(PipelineRoutedStore.java:497)
at voldemort.store.routed.PipelineRoutedStore.getAll(PipelineRoutedStore.java:418)
at voldemort.store.DelegatingStore.getAll(DelegatingStore.java:59)
at voldemort.store.DelegatingStore.getAll(DelegatingStore.java:59)
at voldemort.store.stats.StatTrackingStore.getAll(StatTrackingStore.java:133)
at voldemort.store.serialized.SerializingStore.getAll(SerializingStore.java:122)
at voldemort.store.DelegatingStore.getAll(DelegatingStore.java:59)
at voldemort.store.versioned.InconsistencyResolvingStore.getAll(InconsistencyResolvingStore.java:57)

服务器端配置

stores.xml

<stores>
 <store>
 <name>test</name>
 <persistence>bdb</persistence>
 <description>test</description>
 <owners>test</owners>
 <routing-strategy>consistent-routing</routing-strategy>
 <routing>client</routing>
 <replication-factor>1</replication-factor>
 <required-reads>1</required-reads>
 <required-writes>1</required-writes>
 <key-serializer>
 <type>string</type>
 </key-serializer>
 <value-serializer>
 <type>string</type>
 </value-serializer>
 </store>
</stores>

server.properties

node.id=0
# configs
admin.enable=true
admin.max.threads=40
bdb.cache.evictln=true
bdb.cache.size=12GB
bdb.checkpoint.interval.bytes=2147483648
bdb.checkpointer.off.batch.writes=true
bdb.cleaner.interval.bytes=15728640
bdb.cleaner.lazy.migration=false
bdb.cleaner.min.file.utilization=0
bdb.cleaner.threads=1
bdb.enable=true
bdb.evict.by.level=true
bdb.expose.space.utilization=true
bdb.lock.nLockTables=94
bdb.minimize.scan.impact=true
bdb.one.env.per.store=true
enable.server.routing=false
enable.verbose.logging=false
http.enable=true
nio.connector.selectors=100
num.scan.permits=2
request.format=vp3
restore.data.timeout.sec=1314000
scheduler.threads=24
slop.frequency.ms=300000
socket.enable=true
storage.configs=voldemort.store.bdb.BdbStorageConfiguration, voldemort.store.readonly.ReadOnlyStorageConfiguration
stream.read.byte.per.sec=209715200
stream.write.byte.per.sec=78643200

cluster.xml

<cluster>
 <name>myprodcluster</name>
 <server>
 <id>0</id>
 <host>192.168.1.10</host>
 <http-port>8081</http-port>
 <socket-port>6666</socket-port>
 <admin-port>7777</admin-port>
 <partitions>0, 1</partitions>
 </server>
</cluster>

客户端配置

核心属性

voldemort.max.per.node.connection=500
voldemort.connection.timedout=5000
voldemort.socket.timedout=10000
voldemort.idle.connection.timedout=10

Spring XML配置

<bean id="config" class="voldemort.client.ClientConfig">
 <constructor-arg>
 <props>
 <prop key="bootstrap_urls">${voldemort.url}</prop>
 <prop key="max_connections">${voldemort.max.per.node.connection}</prop>
 <prop key="connection_timeout_ms">${voldemort.connection.timedout}</prop>
 <prop key="idle_connection_timeout_minutes">${voldemort.idle.connection.timedout}</prop>
 <prop key="socket_timeout_ms">${voldemort.socket.timedout}</prop>
 </props>
 </constructor-arg>
</bean>
<bean id="clientFactory" class="voldemort.client.SocketStoreClientFactory" destroy-method="close">
 <constructor-arg index="0" ref="config" />
</bean>
<bean id="storeClient" factory-bean="clientFactory" factory-method="getStoreClient">
 <constructor-arg value="${voldemort.store.name}" />
</bean>

问题分析与解决方案

核心问题拆解

这个异常InsufficientOperationalNodesException提示需要1个成功的节点,但实际0个成功,且失败节点为空,结合连接池最终耗尽的表现,大概率是连接泄漏或请求阻塞导致连接无法回收,再加上getAll()本身的特性放大了问题:

  1. 连接泄漏风险:虽然Spring配置了destroy-method="close"给SocketStoreClientFactory,但如果应用上下文没有正常销毁(比如异常 shutdown),连接池资源无法释放;另外如果代码中频繁创建StoreClient而不复用,也会导致连接积压。
  2. getAll()的性能瓶颈:如果存储的数据量较大,getAll()会一次性拉取所有数据,耗时远超socket_timeout_ms=10000,超时后客户端连接没有被正确回收,导致连接池中的可用连接被耗尽。
  3. 服务器端资源瓶颈:BDB的IO性能可能成为短板,比如checkpoint、cleaner线程不足,或者磁盘IO过高导致请求处理缓慢,客户端超时后连接无法正常释放。

针对性解决方案

1. 排查并修复连接泄漏

  • 确保SocketStoreClientFactory在应用关闭时被正确调用close():对于Web应用,确认容器(如Tomcat) shutdown时Spring上下文能正常销毁;对于独立应用,在退出逻辑中主动调用clientFactory.close()。
  • 复用StoreClient实例:Voldemort的StoreClient是线程安全的,无需每次请求创建新实例,确保全局复用一个实例。
  • 启用连接池监控:通过JMX查看SocketStoreClientFactory的连接池状态,统计连接创建/销毁次数,确认是否存在泄漏。

2. 优化getAll()调用逻辑

  • 避免直接使用getAll():如果数据量较大,改用分页查询或批量获取的方式,拆分请求为多个小请求,减少单连接的占用时间。
  • 调整超时配置:如果业务必须使用getAll(),适当增大socket_timeout_ms(比如调整到30000ms),同时配合缩短idle_connection_timeout_minutes(比如设为5分钟),让空闲连接更快回收。

3. 服务器端性能优化

  • 监控BDB运行状态:查看BDB的日志,检查checkpoint、cleaner的执行频率,若磁盘IO过高,可调整bdb.checkpoint.interval.bytes为更大值(比如4GB),或增加bdb.cleaner.threads数量。
  • 服务器资源监控:实时查看CPU、内存、磁盘IO使用率,确认是否存在资源瓶颈,比如磁盘IO过高则考虑更换更快的存储介质(SSD)。
  • 调整服务器连接参数:增大nio.connector.selectors值(比如到200),提升服务器处理并发连接的能力,避免连接积压。

4. 客户端连接池调优

  • 调整空闲超时:将idle_connection_timeout_minutes从10分钟缩短到5分钟,让闲置连接更快被回收,减少连接池占用。
  • 限制并发请求:如果业务并发量超过max_connections=500,考虑增加该值,同时确保服务器端能承受对应的连接数。

额外提示

针对异常中Failing nodes : []的奇怪现象,建议检查客户端的集群配置刷新机制:Voldemort客户端默认会定期刷新集群配置,可确认是否开启了自动刷新(默认开启),避免客户端缓存的节点状态与实际不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:58:09