SpringBoot + Druid + Mysql + 并发

环境:

Spring Boot 2.4.3

Druid 1.1.23

Mysql 8.0

实现功能:利用乐观锁实现对表中一个字段进行相加操作。

1、Mysql 8.0 加大连接数,登录到Mysql,输入命令:setpersist max_connections=1000;

2、项目中druid配置:

    #表明使用Druid连接池

    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

    # 初始化时建立物理连接的个数

    spring.datasource.initialSize=5

    # 最小连接池数量

    spring.datasource.minIdle=5

    # 最大连接池数量

    spring.datasource.maxActive=1000

    # 获取连接时最大等待时间,单位毫秒

    spring.datasource.maxWait=10000

    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

    spring.datasource.timeBetweenEvictionRunsMillis=60000

    # 连接保持空闲而不被驱逐的最小时间

    spring.datasource.minEvictableIdleTimeMillis=300000

    # 用来检测连接是否有效的sql,要求是一个查询语句

    spring.datasource.validationQuery=SELECT 1 FROM DUAL

    # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

    spring.datasource.testWhileIdle=true

    # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能

    spring.datasource.testOnBorrow=false

    # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

    spring.datasource.testOnReturn=false

    # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。

    spring.datasource.poolPreparedStatements=true

    # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。

    spring.datasource.maxPoolPreparedStatementPerConnectionSize=20

    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计

    spring.datasource.filters=stat,wall,log4j

    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录

    spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000


3、Spring代码

Controller层:

@PostMapping("updateAmount")

public String updateAmount(@RequestBody JSONObject jsonObject)throws SQLException {

    Double amount = jsonObject.getDoubleValue("amount");

    boolean flag =false;

    int count =1;

    for (int i =0; i <3; i++) {

    Integer version =userService.getAmontVersion();

    if (userService.updateAmount(amount,version)) {

        flag =true;

        break;

    }

    count++;

    }

    System.out.println("==========  count: " + count +",  flag: " + flag);

    if (flag) {

        return "successfully";

    }

    return "failed";

}


Service层:

@Override

public boolean updateAmount(Double amount,Integer version)throws SQLException {

    return druidDao.updateAmount(amount, version);

}

@Override

public Integer getAmontVersion()throws SQLException {

    return druidDao.getAmontVersion();

}


DAO层:

@Override

public boolean updateAmount(Double amount,Integer version)throws SQLException {

    QueryRunner queryRunner =new QueryRunner();

    String sql ="update t_pay_amount set amount=amount+" + amount;

    sql +=", version=version+1";

    sql +=" where version=" + version;

    Connection connection =dataSource.getConnection();

    int result =queryRunner.update(connection, sql);

    connection.close();

    return (result ==1) ?true :false;

}

@Override

public Integer getAmontVersion()throws SQLException {

    QueryRunner queryRunner =new QueryRunner();

    String sql ="select version from t_pay_amount";

    Connection connection =dataSource.getConnection();

    Integer version = ((Integer)queryRunner.query(connection,sql,new ScalarHandler()));

    connection.close();

    if (null ==version) {

        return 0;

    }

    return version;

}


重点在于DAO在使用Connection连接后,要立即关闭,否则会导致连接突然增多,其它请求过来时无法连接到数据库,引起连接超时,从而请求失败。

你可能感兴趣的:(SpringBoot + Druid + Mysql + 并发)