一、参考

  1. 实战:搞懂数据库连接池和Druid连接池
  2. 数据库连接池
  3. mySQL数据库druid连接池配置

二、为什么要有数据库连接池

传统数据库连接的问题?

在这里插入图片描述

  1. 频繁创建和关闭连接:
  • 每次执行 SQL 都需要创建连接,操作完成后关闭连接。
  • 创建和关闭连接是非常耗时的操作(涉及网络通信、身份验证等)。
  1. 资源浪费:
  • 连接对象占用系统资源(如内存、CPU)。
  • 频繁创建和关闭连接会导致资源浪费。
  1. 性能瓶颈:
  • 高并发场景下,频繁创建连接会导致数据库性能下降。
  1. 连接数限制:
  • 数据库对同时打开的连接数有限制,频繁创建连接可能导致连接数耗尽

连接池的优势

  • 复用连接: 连接池预先创建一定数量的连接,应用程序从池中获取连接,使用完毕后归还连接。
  • 减少开销: 避免了频繁创建和关闭连接的开销,提高了性能。
  • 资源控制: 可以限制最大连接数,防止数据库连接数过多导致资源耗尽。
  • 提高响应速度: 连接池中的连接是预先创建的,应用程序可以快速获取连接。

连接池的工作原理

在这里插入图片描述

核心组件:

  • 连接池管理器: 负责创建、管理和销毁连接池。

  • 连接池: 维护一组数据库连接,提供连接的获取和归还功能。

  • 空闲连接: 当前未被使用的连接,存放在连接池中。

  • 活动连接: 当前正在被使用的连接。

工作流程:

  1. 初始化连接池: 在应用程序启动时,连接池会预先创建一定数量的数据库连接。
  2. 获取连接:
    • 应用程序从连接池中请求一个连接。
    • 如果池中有空闲连接,则直接返回;如果没有空闲连接且未达到最大连接数,则创建新连接;如果已达到最大连接数,则等待或抛出异常。
  3. 使用连接: 应用程序使用连接执行数据库操作。
  4. 归还连接: 操作完成后,应用程序将连接归还给连接池,而不是关闭连接。
  5. 连接回收: 连接池会定期检查连接的有效性,回收无效连接并创建新连接。

三、常用连接池对比

常见的连接池有C3P0、Druid、HikariCP 、DBCP

  1. JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方来实现。

  2. C3P0数据库连接池,速度相对较慢(只是慢一丢丢),但是稳定性很好,Hibernate,Spring底层用的就是C3P0

  3. DBCP数据库连接池,速度比C3P0快,但是稳定性差。

  4. Proxool数据库连接池,有监控连接池状态的功能,但稳定性仍然比C3P0差一些。

  5. BoneCP数据库连接池,速度较快。

  6. Druid数据库连接池(德鲁伊连接池),由阿里提供,集DBCP,Proxool,C3P0连接池的优点于一身,是日常项目开发中使用频率最高的数据库连接池。

  7. HikariCP:HikariCP是一个轻量级、高效的JDBC连接池,具有快速启动和低延迟的特点。 HikariCP的设计目标是提供极佳的性能和可靠性,同时尽量减少资源消耗和开销。HikariCP支持各种JDBC驱动程序和数据源。相比于其他连接池,HikariCP配置简单,易于使用。

特性 HikariCP Apache Commons DBCP Tomcat JDBC Pool H2 Database Connection Pool c3p0 Druid
性能 非常高 一般 一般 一般 一般 非常高
配置简单性 中等 中等 中等 中等
可定制性 中等 中等
监控和统计功能
防火墙功能
社区活跃度 中等 中等 中等
适用场景 各种场景 一般场景 Tomcat 环境 嵌入式数据库场景 各种场景 大型互联网企业环境
是否支持连接池复用
支持的数据库 所有主流数据库 所有主流数据库 所有主流数据库 H2 Database 所有主流数据库 所有主流数据库

目前主流使用 Druid 和 HikariCP 数据库连接池

  • HikariCP,号称性能最好的数据库连接池。Spring Boot 2.X 版本,默认采用 HikariCP 。

  • Druid,为监控而生的数据库连接池。阿里大规模采用 Druid 。

HikariCP 连接池

  • HikariCP 是一个高性能的 JDBC 连接池实现,以其轻量、快速和简单著称。它的设计目标是尽可能减少开销,提供最快的数据库连接获取速度。

  • 特点

    • 轻量:代码量少,依赖少。
    • 高性能:在大多数场景下性能优于其他连接池。
    • 简单易用:配置简单,开箱即用。
    • 可靠性高:经过严格测试,稳定性强。
    • HikariCP 通过优化代码和减少锁竞争,显著提高了连接获取的速度
    • 减少了不必要的对象创建和垃圾回收,降低了 JVM 的开销
    • 自动维护连接池的健康状态,回收无效连接

HikariCP 单数据源

  1. 引入依赖
<dependencies>
    <!--此依赖默认使用Hikari连接池,实现对数据库连接池的自动化配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <!-- 默认版本是 8.0.22-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
</dependencies>
  1. 在application.yml中,添加 HikariCP 配置
server:
  port: 8010
spring:
  #配置数据源
  datasource:
    url: jdbc:mysql://localhost:33306/atguigudb?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      # 连接池中允许的最小连接数。缺省值:10
      minimum-idle: 10
      # 连接池中允许的最大连接数。缺省值:10
      maximum-pool-size: 100
      # 自动提交
      auto-commit: true
      # 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
      idle-timeout: 600
      # 连接池名字
      pool-name: 泡泡的HikariCP
      # 一 个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒
      max-lifetime: 1800000
      # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
      connection-timeout: 30000
  1. 定义控制器,调用数据库
package com.hb.controller;


import com.hb.pojo.Student;
import com.hb.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;

@RestController
@Api(tags = {"Student模块"}, value = "数据字典控制器")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @Autowired
    DataSource dataSource;

    @ApiOperation("mybatis 测试")
    @GetMapping("/getUser/{id}")
    public Student GetUser(@PathVariable int id) {
        System.out.println(dataSource);
        Student student = studentService.sell(id);
        return student;
    }
}

在这里插入图片描述

HikariCP 多数据源

后续补充

Druid 连接池

  • Druid 是阿里巴巴开源的数据库连接池实现**,除了高性能外,还提供了丰富的监控和统计功能,适合需要深度监控和管理的场景**

  • 特点

    • 高性能:性能接近 HikariCP。
    • 功能丰富:支持 SQL 监控、防火墙、加密等功能。
    • 监控强大:内置监控页面,支持实时查看连接池状态和 SQL 执行情况
    • 扩展性强:支持自定义过滤器
  • 核心优势

    • SQL 监控:可以监控 SQL 的执行时间、执行次数等,帮助优化 SQL 性能。
    • 防火墙功能:提供 SQL 防火墙,防止恶意 SQL 注入。
    • 加密支持:支持数据库密码加密,提高安全性。
    • 扩展性:支持自定义过滤器,方便扩展功能

druid 使用案例

  1. 引入依赖
<dependencies>
    <!-- 如果使用druid-spring-boot-starter, 那么需要在启动类上使用@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class) -->
    <!--引入druid数据源-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.16</version>
    </dependency>
    <!-- 默认版本是 8.0.22-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
</dependencies>
  1. 在application.yml中,添加 druid 配置
    一定要指明 spring.datasource.type = com.alibaba.druid.pool.DruidDataSource , 表明现在使用的事 druid 连接池
server:
  port: 8010
spring:
  #配置数据源
  datasource:
    url: jdbc:mysql://localhost:33306/atguigudb?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    # druid-spring-boot-starter 依赖自动生效 druid,可以不配置 type 属性,但建议配置
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 10 # 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
      min-idle: 10 # 最小连接池数量
      maxActive: 200 # 最大连接池数量
      maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置
      timeBetweenEvictionRunsMillis: 60000 # 关闭空闲连接的检测时间间隔.Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
      minEvictableIdleTimeMillis: 300000 # 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间
      #      WebStatFilter:用于收集 Web 应用程序的 SQL 慢查询日志。
      web-stat-filter:
        enabled: true
      # StatViewServlet:提供了一个可视化的监控页面,可以查看连接池的各项指标。
      stat-view-servlet: # http://localhost:8010/druid/index.html 访问监控界面
        enabled: true
        url-pattern: /druid/*
        login-username: druid
        login-password: druid
      #        allow: 127.0.0.1可根据需要配置IP白名单
      #        deny: 可根据需要配置IP黑名单
      validationQuery: SELECT 1 FROM DUAL # 验证数据库服务可用性的sql.用来检测连接是否有效的sql 因数据库方言而差, 例如 oracle 应该写成 SELECT 1 FROM DUAL
      testWhileIdle: true # 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRun
      testOnBorrow: false # 申请连接时直接检测连接是否有效.申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      testOnReturn: false # 归还连接时检测连接是否有效.归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      poolPreparedStatements: true # 开启PSCache
      maxPoolPreparedStatementPerConnectionSize: 20 #设置PSCache值
      connectionErrorRetryAttempts: 3 # 连接出错后再尝试连接三次
      breakAfterAcquireFailure: true # 数据库服务宕机自动重连机制
      timeBetweenConnectErrorMillis: 300000 # 连接出错后重试时间间隔
      asyncInit: true # 异步初始化策略
      remove-abandoned: true # 是否自动回收超时连接
      remove-abandoned-timeout: 1800 # 超时时间(以秒数为单位)
      transaction-query-timeout: 6000 # 事务超时时间
      filters: stat,wall,log4j2
      useGlobalDataSourceStat: true #合并多个DruidDataSource的监控数据
      connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 #通过connectProperties
  1. 定义控制器,调用数据库
package com.hb.controller;


import com.hb.pojo.Student;
import com.hb.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;

@RestController
@Api(tags = {"Student模块"}, value = "数据字典控制器")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @Autowired
    DataSource dataSource;

    @ApiOperation("mybatis 测试")
    @GetMapping("/getUser/{id}")
    public Student GetUser(@PathVariable int id) {
        System.out.println(dataSource);
        Student student = studentService.sell(id);
        return student;
    }
}

在这里插入图片描述

durid 监控界面

  1. springboot 添加开启监控页面的配置
server:
  port: 8010
spring:
  #配置数据源
  datasource:
    url: jdbc:mysql://localhost:33306/atguigudb?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    # druid-spring-boot-starter 依赖自动生效 druid,可以不配置 type 属性,但建议配置
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      #      WebStatFilter:用于收集 Web 应用程序的 SQL 慢查询日志。
      web-stat-filter:
        enabled: true
      # StatViewServlet:提供了一个可视化的监控页面,可以查看连接池的各项指标。
      stat-view-servlet: # http://localhost:8010/druid/index.html 访问监控界面
        enabled: true
        url-pattern: /druid/*
        login-username: druid
        login-password: druid
      #        allow: 127.0.0.1可根据需要配置IP白名单
      #        deny: 可根据需要配置IP黑名单
  1. 浏览器输入 http://localhost:8010/druid/

在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐