数据库必知必会系列:数据库连接池与连接管理

作者:禅与计算机程序设计艺术

1.简介

连接数据库是一个应用程序中最重要的环节。在此之前,开发者需要自己构建、管理、维护和优化数据库连接。而随着分布式、微服务架构的发展,应用服务器的数量不断增加,单纯依靠程序内部处理连接的方式已经无法支撑需求。为了解决这个问题,连接池(Connection Pool)应运而生。连接池就是在创建连接时预先建立若干个连接放入一个池子,当需要使用某个连接时从池子里取出一条记录用完后再归还给池子。这样可以避免频繁地创建连接,提高性能并降低资源消耗。此外,连接池还能够有效防止数据库连接泄露。 连接池又分为两类:静态连接池和动态连接池。静态连接池指的是在系统启动时就预先创建好指定数量的数据库连接,之后每次调用都直接从池子里取出连接进行数据交互;动态连接池则根据实际需要自动创建和销毁连接。两种连接池各有优缺点,在不同的场景下更加合适。 本文将对数据库连接池的基本原理、实现方式、应用场景等方面进行阐述。希望通过阅读本文,能对数据库连接池有全面的理解,并灵活应用到实际工作中。

2.连接池基本原理

2.1 概念定义及分类

连接池(Connection pool)是一种提升应用系统性能的技术。它主要用于减少创建新连接所需的时间,同时确保连接可用性。主要功能如下:

  1. 对数据库连接的复用:使用连接池技术,可重用数据库连接,避免频繁打开关闭数据库连接造成额外开销。在业务高峰期间,使用连接池能提升系统整体运行效率,减少资源浪费。

  2. 提升数据库访问速度:由于连接池缓存了数据库连接,因此重复使用的次数越多,其速度也就越快。在业务低谷时段,释放连接后会等待一定的时间,但只要连接被再次请求使用,就会很快恢复。

  3. 提升系统稳定性:连接池采用长连接的方式,可以有效避免因连接过多导致的连接数过大或过小的问题,且连接不会超时。

  4. 可控性及监控能力:使用连接池后,无需关注数据库连接是否正常、过多或过少,只需要保证每个数据库连接能得到有效利用即可。监控连接池中的连接状态、总容量及使用情况,可直观掌握当前连接池的负载、流量及使用情况,做到精准、实时地监控和管理。

基于以上四点特性,连接池可分为以下三种类型:

  1. 固定大小的连接池:该类型的连接池的最大容量是固定的,应用程序初始化时,就向池子里添加固定数量的连接,使用完成后再返还给池子。典型的代表产品有 Oracle 的 OCI 和 SQL Server 的 ODBC。

  2. 可扩展的连接池:该类型的连接池的最大容量不是固定的,随时可以增加或者删除连接。当连接池空闲时,应用程序不需要等待,可以创建一个新的连接,加入池子,当连接数量达到上限时,则等待其他线程返回连接后再继续分配。典型的代表产品有 Apache DBCP 和 C3P0。

  3. 池化的连接池:池化的连接池既能够实现连接复用,也能保证连接的可靠性。其原理是为相同的数据库配置多个连接,并在获取连接前首先检查池内是否存在可用的连接。如果没有可用连接,才重新创建新的连接。优点是在高并发情况下,仍然能够获得较好的性能,且保证了连接的可用性。典型的代表产品有 Hibernate SessionFactory。

2.2 连接池的实现方式

连接池的实现方式主要有两种:

  1. 代理模式(Proxy Pattern):即由中间件(如 Nginx 或 HA Proxy)实现连接池,应用程序只与该代理通信,而非数据库。该模式下,客户端需要通过代理获取连接,而不是直接与数据库建立连接。代理接收客户端的请求后,查找连接池中是否有可用的连接,若有则分配之,若没有,则新建一个连接,然后返回给客户端。这种模式下,客户端需要与代理建立连接,且在请求结束后必须关闭连接。

  2. 数据源模式(DataSource Pattern):即在应用程序中集成 javax.sql.DataSource 接口,应用程序直接与 DataSource 对象通信,而不是与数据库建立连接。这种模式下,应用程序需要通过 DataSource 对象获取数据库连接。DataSource 提供了一个标准的方法来获取连接,并封装了所有连接细节,包括数据库驱动、连接字符串、用户名密码等,简化了连接过程。DataSource 中的 connection 方法在首次执行时,会从连接池中获取或新建连接,并将其缓存在 DataSource 中,供后续请求使用。当连接处于闲置状态超过一定时间,会自动被回收。

2.3 连接池的应用场景

连接池的应用场景很多,以下几类常见场景列举:

  1. JDBC 数据源:对于支持 JDBC API 的编程语言来说,通过 DataSource 可以提供数据库连接池功能,减少数据库连接的创建和销毁次数,有效提升应用性能。

  2. Spring Framework:Spring 支持各种 ORM 框架,包括 MyBatis、Hibernate 等,它们都需要通过 DataSource 来访问数据库,所以可以利用 Spring 提供的 DataSourceUtils 工具类来创建 DataSource 对象。

  3. 分布式环境:由于分布式环境下,应用程序服务器之间的网络延迟和传输失败等原因可能会影响数据库连接的稳定性,而连接池的存在使得数据库连接在任意时刻都保持一定数量,避免出现某台服务器拥有大量连接而另一台服务器没有连接的情况。

  4. Web 应用服务器集群:Web 应用服务器集群一般部署在多个物理机上,并且由于各服务器之间的网络互联性,在高并发场景下会发生短暂的连接失败。连接池的存在,可以保证每台服务器的连接数量限制在一个比较合理的值,以避免出现单台服务器拥有大量连接而其它服务器没有连接的情况。

  5. 大并发访问场景:对于大规模的并发访问场景,如秒杀等场景,连接池能够有效控制数据库连接的数量,避免数据库被压垮。另外,连接池也可以对并发访问进行排队和限制,有效保护数据库资源。

3.MySQL数据库连接池——HikariCP实现方式分析

3.1 HikariCP简介

HikariCP (High-Performance JDBC Connection Pool) 是第三方开源的数据库连接池。它是一个强大的纯 Java 库,通过使用JDBC API 来连接数据库,并提供对数据库连接池的配置、监视和管理。它非常轻量级,可以在各种连接场景中提高数据库连接的性能和响应速度。HikariCP 提供快速而简单的配置项,同时也提供了自动机器学习配置的选项。可以说,HikariCP 是一个值得尝试的数据库连接池框架。

3.2 HikariCP概览

3.2.1 下载安装HikariCP

下载地址:https://github.com/brettwooldridge/HikariCP

git clone https://github.com/brettwooldridge/HikariCP.git

导入maven项目:

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>2.7.2</version>
</dependency>

3.2.2 配置及使用HikariCP

(1)加载配置文件

配置文件名称:hikari.properties

dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
dataSource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
dataSource.user=root
dataSource.password=<PASSWORD>
poolName=myPool
maximumPoolSize=10
connectionTimeout=30000
idleTimeout=600000
maxLifetime=1800000
minimumIdle=10

注意:

  1. dataSourceClassName:数据库驱动类名,这里设置为MySQL驱动
  2. dataSource.url:数据库连接URL
  3. dataSource.user:数据库用户名
  4. dataSource.password:数据库密码
  5. poolName:连接池名称
  6. maximumPoolSize:连接池中允许的最大连接数
  7. connectionTimeout:建立连接的超时时间(毫秒)
  8. idleTimeout:连接存活时间,默认600000ms(十分钟)
  9. maxLifetime:连接最大生命周期,默认1800000ms(三十分钟)
  10. minimumIdle:最小空闲连接数,默认10个
(2)Java代码配置HikariCP
HikariConfig config = new HikariConfig("hikari.properties"); //加载配置文件
try {
  DataSource dataSource = new HikariDataSource(config); //创建数据源
  //... 使用数据源...
} catch (Exception e) {
  e.printStackTrace();
} finally {
  config.close();
}
(3)Spring Boot集成HikariCP

spring-boot-starter-data-jpa依赖引入HikariCP:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 引入HikariCP -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

application.properties设置数据库连接信息:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=<PASSWORD>
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.min-idle=10

SpringBoot的yml配置文件设置数据库连接信息:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useSSL=false
    username: root
    password: admin
    hikari:
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      min-idle: 10

注意

  1. 在使用过程中,HikariCP可以通过参数修改数据库连接参数。如:setNetworkTimeout()方法,setConnectionTestQuery()方法,setValidationTimeout()方法等。
  2. 在使用过程中,建议设置minimumIdle的数值比最大连接数略小一些,以提升数据库连接利用率。

猜你喜欢

转载自blog.csdn.net/universsky2015/article/details/133385403