如何追踪Ignite WriteBehindCache数据源指标及排查性能瓶颈
Spring Boot嵌入式Ignite+Oracle压测性能问题排查与优化
问题背景
Spring Boot应用使用嵌入式Ignite作为服务节点,数据写入Oracle数据库。每个微服务请求包含4-5次缓存操作,其中2个缓存同时配置了WRITEBEHIND=true和WRITETHROUGH=true(同步/异步混合写入)。压测时发现每个请求耗时达3秒,请求会卡在上某一缓存操作环节。采用Hikari连接池,环境为8核32GB内存(默认堆外存储,未配置DataRegion),Ignite嵌入式日志无报错。
需要解决以下问题:
- 排查Ignite Put/Get操作耗时原因,区分DB连接耗时与实际Insert查询耗时;
- 获取Ignite内部可观测手段,定位性能瓶颈;
- 针对该场景提供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
相关产品推荐
相关产品推荐

