JPA 并发查询同一条数据时的效率问题

2022-02-25 17:56:54 +08:00
 joooooker21

伪代码

    public RespData findOrderTest(@RequestParam String orderCode,@RequestParam String strategy) {
        TbOrder tbOrder = orderDao.findByOrderCodeAndStrategy(orderCode, strategy);
        
        //do something
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return RespData.success(tbOrder);
    }

使用 jmeter 并发调用,查询条件不变,反复查询同一条数据,发现查询速率变慢

正常耗时日志

    `---[5054.53776ms] cn.*.PatientAppController:findOrderTest()
        +---[54.165884ms] cn.*.TbOrderDao:findByOrderCodeAndStrategy() #349
        +---[0.079756ms] javax.persistence.EntityManager:clear() #350
        `---[0.018264ms] cn.*.RespData:buildSuccess() #363

测试期间接口耗时逐渐增加,异常耗时日志

    `---[29406.81247ms] cn.*.PatientAppController:findOrderTest()
        +---[24406.507885ms] cn.*.TbOrderDao:findByOrderCodeAndStrategy() #349
        +---[0.036484ms] javax.persistence.EntityManager:clear() #350
        `---[0.020533ms] cn.*.RespData:buildSuccess() #363

已排除是数据库性能问题,怀疑是 jpa 内部的实现机制所致,多番测试还是没有找到问题,分享出来给大家看看,请大佬指教

2019 次点击
所在节点    Java
10 条回复
zhady009
2022-02-25 18:22:47 +08:00
mark 下 mongodb 好像也有这种情况

控制台里查一样的语句很快就返回

trace 的时候发现也是慢在 repository 的方法里 用了 10 秒 而且就 4000 条数据

版本是 2.4 的
joooooker21
2022-02-25 18:25:33 +08:00
查询后直接返回,速度是不会变慢的。怀疑是 jpa 内部有某种锁的机制
wolfie
2022-02-25 18:31:08 +08:00
看看有没有缓存开关
mango88
2022-02-25 19:04:51 +08:00
压测多久发生一次 ? 变慢时,jvm 是否在 GC ?
siweipancc
2022-02-25 19:48:07 +08:00
orz 你开个纯接口,里边也睡一会,并发下还是会重现的
TheCure
2022-02-25 19:58:10 +08:00
joooooker21
2022-02-25 21:44:19 +08:00
@wolfie 尝试过 EntityManager.clear() 情况还是一样

@mango88 基本上持续几秒就开始出现这样的情况,排除是 GC

@siweipancc 尝试过,还是会重现
1194129822
2022-02-25 21:59:00 +08:00
这不是 JPA 的问题,你换成 Mybatis 之类也会出现同样的情况。很明显是连接池的问题,Connection 一般都是有限的,你并发高,把 Connection 占完了,而且迟迟不释放。后面线程阻塞在获取 Connection ,你可以看一下你用的是什么 DataSource ,Hikari 默认只有 10 个连接。你把连接数调到几百试一下,你这就相当于慢查询,造成的雪崩效应。但是真实环境下 Connection 也不能太多,不然雪崩的就是数据库了,JDBC 的阻塞性其实保护的是数据库。
joooooker21
2022-02-26 00:08:22 +08:00
@1194129822 多谢分享。我有个疑问,数据库的 Connection 难道不是在返回查询结果后就立即释放了?另外这段代码是也并没有开启事务
zhenjiachen
2022-02-26 08:46:13 +08:00
我觉得 8 楼说的对,你可以看一下你的连接池支不支持指标,看一下指标就可以看出是不是并发后把链接用完了导致其他请求等待获取连接。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/836450

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX