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

如何追踪Ignite WriteBehindCache数据源指标及排查性能瓶颈

Spring Boot嵌入式Ignite+Oracle压测性能问题排查与优化

问题背景

Spring Boot应用使用嵌入式Ignite作为服务节点,数据写入Oracle数据库。每个微服务请求包含4-5次缓存操作,其中2个缓存同时配置了WRITEBEHIND=true和WRITETHROUGH=true(同步/异步混合写入)。压测时发现每个请求耗时达3秒,请求会卡在上某一缓存操作环节。采用Hikari连接池,环境为8核32GB内存(默认堆外存储,未配置DataRegion),Ignite嵌入式日志无报错。

需要解决以下问题:

  1. 排查Ignite Put/Get操作耗时原因,区分DB连接耗时与实际Insert查询耗时;
  2. 获取Ignite内部可观测手段,定位性能瓶颈;
  3. 针对该场景提供Ignite优化配置建议。

附相关配置代码

缓存存储配置

<property name="readThrough" value="true" />
<property name="writeThrough" value="true" /> 
<property name="writeBehindEnabled" value="true"/>
<property name="writeBehindFlushThreadCount" value="8" />

Hikari数据源配置

<bean id="dataSourceUY" class="com.zaxxer.hikari.HikariDataSource">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
    <property name="jdbcUrl" value="jdbc:oracle:thin:@db.oracle.com:1531/TEST" />
    <property name="username" value="myapp" />
    <property name="password" value="db_pwd" />
    <property name="maximumPoolSize" value="50" />
    <property name="minimumIdle" value="10" />
    <property name="idleTimeout" value="20000" />
    <property name="connectionTimeout" value="30000"/>
    <property name="poolName" value="dataSourceUY"/>
    <property name="maxLifetime" value="180000"/>
</bean>

Ignite节点配置

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="dataStorageConfiguration">
        <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
            <property name="defaultDataRegionConfiguration">
                <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                    <property name="metricsEnabled" value="true"/>
                </bean>
            </property>
        </bean>
    </property> 
    <!--<property name="executorConfiguration">
        <list>
            <bean class="org.apache.ignite.configuration.ExecutorConfiguration">
                <property name="name" value="orchPool"/>
                <property name="size" value="10"/>
            </bean>
        </list>
    </property> -->
    <property name="peerClassLoadingEnabled" value="true" />
    <property name="igniteInstanceName" value="MyCluster" />
    <property name="systemThreadPoolSize" value="20" />
    <property name="stripedPoolSize" value="20" />
    <property name="clientMode" value="false" />
    <property name="workDirectory"  value="/ignite/workdir/app" />
    <property name="discoverySpi">
        <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
            <property name="ipFinder">
                <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                    <property name="addresses">
                        <list>
                            <value>myapp-services:47500..47520</value>
                        </list>
                    </property>
                </bean>
            </property>
        </bean>
    </property> 
</bean>

1. 排查Put/Get耗时:区分DB连接与Insert查询耗时

  • Hikari连接池日志追踪:将com.zaxxer.hikari日志级别设为DEBUG,可打印连接获取等待时间、连接创建/释放耗时,直接定位是否因连接池耗尽导致等待。
  • Oracle JDBC日志监控:开启oracle.jdbc的DEBUG日志,记录SQL执行的起止时间,拆分出实际Insert/Update操作的耗时,区分是DB执行慢还是连接等待。
  • Ignite缓存拦截器埋点:自定义CacheInterceptor,在onAfterPut/onAfterGet方法中记录操作耗时,结合Hikari/JDBC日志,精准定位缓存操作中DB交互的时间占比。
  • 线程栈采样分析:使用jstack定期抓取线程快照,或用async-profiler进行CPU/阻塞采样,查看线程卡在Ignite的DB存储环节(等待连接还是等待SQL执行),或是Ignite内部线程池阻塞。

2. Ignite内部可观测手段

  • JMX监控:通过JConsole/VisualVM连接Ignite节点,查看以下核心指标:
    • CacheMetrics:writeThroughOperationsCount、writeBehindQueueSize、writeBehindErrors(判断异步写队列是否积压);
    • ThreadPoolMetrics:stripedPool、systemPool、write-behind线程池的活跃线程数、队列长度(判断线程池是否过载);
    • Hikari连接池JMX指标:ActiveConnections、IdleConnections、ConnectionWaitTime(监控连接池状态)。
  • Ignite存储层日志:将org.apache.ignite.internal.processors.cache.store日志级别设为DEBUG,可直接看到缓存存储操作的详细耗时日志(如Store operation completed in X ms)。
  • Ignite metrics文件:查看Ignite work目录下自动生成的metrics统计文件,定期收集缓存、线程池、存储的性能数据,分析长期趋势。
  • 缓存索引检查:如果使用SQL缓存,执行EXPLAIN命令查看DB查询计划,确认是否存在索引缺失导致的慢查询。

3. 优化配置建议

缓存存储配置修复

Ignite中writeBehindEnabled=true会覆盖writeThrough=true(异步写优先级高于同步写),当前配置存在逻辑冲突,需明确业务需求:

  • 若需要异步写:保留writeBehindEnabled=true,移除writeThrough=true,并补充批量写入配置:
    <property name="writeBehindBatchSize" value="100" /> <!-- 批量写入条数 -->
    <property name="writeBehindFlushFrequency" value="500" /> <!-- 批量刷新间隔(ms) -->
    
  • 若需要同步写:保留writeThrough=true,移除writeBehindEnabled=true,确保数据强一致性。

DataRegion内存配置

当前未配置堆外内存大小,易导致内存不足或频繁换页,建议根据32GB内存调整:

<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
    <property name="metricsEnabled" value="true"/>
    <property name="maxSize" value="#{20 * 1024 * 1024 * 1024}" /> <!-- 20GB堆外内存 -->
    <property name="pageMemorySize" value="#{4 * 1024 * 1024 * 1024}" /> <!-- 4GB页内存 -->
</bean>

Hikari连接池优化

  • 调整maxLifetime:当前3分钟(180000ms)过短,Oracle默认连接超时远长于此,建议设为30分钟(1800000ms),减少连接重建开销;
  • 统一maximumPoolSize与minimumIdle:将minimumIdle设为50,避免连接池动态调整的性能损耗;
  • 监控连接池水位:压测时若ActiveConnections持续达到50,需评估DB的并发处理能力,或调整缓存写入策略(如增加WRITEBEHIND批量大小)。

Ignite线程池优化

  • 调整stripedPoolSize:8核机器建议设为2*CPU核心数=16,避免线程过多导致上下文切换;
  • 启用自定义线程池:取消注释executorConfiguration,将缓存存储操作绑定到自定义线程池,避免占用系统线程池:
    <property name="executorConfiguration">
        <list>
            <bean class="org.apache.ignite.configuration.ExecutorConfiguration">
                <property name="name" value="orchPool"/>
                <property name="size" value="16"/> <!-- 与CPU核心数匹配 -->
            </bean>
        </list>
    </property>
    
  • 调整writeBehindFlushThreadCount:当前8与CPU核心数匹配,若DB能承受更高并发,可适当调至10-12,但需确保Hikari连接池有足够连接支撑。

网络与集群优化

  • 验证TcpDiscoverySpi的地址配置:确保myapp-services能正常解析,端口47500-47520开放,避免集群节点发现延迟影响缓存操作;
  • 关闭不必要的特性:若无需跨节点类加载,可将peerClassLoadingEnabled设为false,减少集群通信开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 22:55:56