V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
joooooker21
V2EX  ›  Java

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

  •  
  •   joooooker21 · 2022-02-25 17:56:54 +08:00 · 2024 次点击
    这是一个创建于 1037 天前的主题,其中的信息可能已经有所发展或是发生改变。

    伪代码

        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 内部的实现机制所致,多番测试还是没有找到问题,分享出来给大家看看,请大佬指教

    10 条回复    2022-02-26 08:46:13 +08:00
    zhady009
        1
    zhady009  
       2022-02-25 18:22:47 +08:00
    mark 下 mongodb 好像也有这种情况

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

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

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

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

    @siweipancc 尝试过,还是会重现
    1194129822
        8
    1194129822  
       2022-02-25 21:59:00 +08:00   ❤️ 1
    这不是 JPA 的问题,你换成 Mybatis 之类也会出现同样的情况。很明显是连接池的问题,Connection 一般都是有限的,你并发高,把 Connection 占完了,而且迟迟不释放。后面线程阻塞在获取 Connection ,你可以看一下你用的是什么 DataSource ,Hikari 默认只有 10 个连接。你把连接数调到几百试一下,你这就相当于慢查询,造成的雪崩效应。但是真实环境下 Connection 也不能太多,不然雪崩的就是数据库了,JDBC 的阻塞性其实保护的是数据库。
    joooooker21
        9
    joooooker21  
    OP
       2022-02-26 00:08:22 +08:00
    @1194129822 多谢分享。我有个疑问,数据库的 Connection 难道不是在返回查询结果后就立即释放了?另外这段代码是也并没有开启事务
    zhenjiachen
        10
    zhenjiachen  
       2022-02-26 08:46:13 +08:00 via iPhone
    我觉得 8 楼说的对,你可以看一下你的连接池支不支持指标,看一下指标就可以看出是不是并发后把链接用完了导致其他请求等待获取连接。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1483 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:10 · PVG 01:10 · LAX 09:10 · JFK 12:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.