分库分表JVM内存泄漏定位

Table of Contents

内存泄漏

sharding-jdbc执行结果合并

解决方法


 

内存泄漏

采用sharding-jdbc分库分表后,执行自动化测试脚本,总是遇到响应超时。查看测试环境服务器发现已经内存崩溃。

由于jvm启动参数已经设置了 -XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath,下载jvm dump文件: heap_hprof_200617_155545.bin。

这里使用Java性能分析工具jprofiler11,执行命令: \jprofiler11\bin\jpanalyze.exe  heap_hprof_200617_155545.bin ,解析dump bin文件,在本地目录生成 heap_hprof_200617_155545.hprof。

点击 jprofiler11,选择Open a snapshot 加载dump文件,选择hprof文件。如下:

打开hprof文件文件后,依次打开Heap Walker->Current Object->Biggest Objects

可以看到mysql查询结果加起来占用了 460M的内存。

由于服务器堆内存总共也就1G,加上其他占用,一个查询超过了可用堆内存,造成内存泄漏。

选中造成内存泄漏的内存大对象,右键打开界面,选择 Merged incoming references

 

sharding-jdbc执行结果合并

以前不会内存泄漏,基于sharding-jdbc分库分表后才频繁出现。

打开大内存对象Reference试图后,我们重点关注sharding-jdbc相关类。

最终定位到:org.apache.shardingsphere.sharding.merge.dql.iterator.IteratorStreamMergedResult

根据后台日志,自动化脚本触发了一些非分片键查询,只有非分片键作为查询条件会产生跨分片查询,跨分片查询的原理是:通过线程池并发请求到所有符合路由规则的目标分表,然后对所有结果进行归并。

sql简化如下。由于items_type非分片键,sharding-jdbc首先并行查询出所有满足条件的结果集,然后调用遍历结果集归并。

SELECT
	*
FROM
	sku
WHERE
	items_type = 4
ORDER BY
	ctime DESC

归并原理如下:

在这里插入图片描述

并行查询加sharding-jdbc中间层的结果归并,占用内存大大超过分库分表前。

解决方法

原来的查询方法从全量查询更改为分页查询。

适当调大最大堆内存: -Xms2G -Xmx2G。

基于hibernat validator框架结合javax.validation.constraints.Min等注解,对输入参数增加校验,在java应用层拦截调非法请求。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值