第09章 连接池
连接池的理解
不使用连接池有啥问题
Connection对象是重量级对象,创建Connection对象就是建立两个进程之间的通信,非常耗费资源。一次完整的数据库操作,大部分时间都耗费在连接对象的创建。
第一个问题:每一次请求都创建一个Connection连接对象,效率较低。
第二个问题:连接对象的数量无法限制。如果连接对象的数量过高,会导致mysql数据库服务器崩溃。
使用连接池来解决什么问题
提前创建好N个连接对象,将其存放到一个集合中(这个集合就是一个缓存)。
用户请求时,需要连接对象直接从连接池中获取,不需要创建连接对象,因此效率较高。
另外,连接对象只能从连接池中获取,如果没有空闲的连接对象,只能等待,这样连接对象创建的数量就得到了控制。
javax.sql.DataSource
连接池有很多,不过所有的连接池都实现了 javax.sql.DataSource 接口。也就是说我们程序员在使用连接池的时候,不管使用哪家的连接池产品,只要面向javax.sql.DataSource接口调用方法即可。
另外,实际上我们也可以自定义属于我们自己的连接池。只要实现DataSource接口即可。
连接池的属性
对于一个基本的连接池来说,一般都包含以下几个常见的属性:
- 初始化连接数(initialSize):连接池初始化时创建的连接数。
- 最大连接数(maxActive):连接池中最大的连接数,也就是连接池所能容纳的最大连接数量,当连接池中的连接数量达到此值时,后续请求会被阻塞并等待连接池中有连接被释放后再处理。
- 最小空闲连接数量(minIdle): 指连接池中最小的空闲连接数,也就是即使当前没有请求,连接池中至少也要保持一定数量的空闲连接,以便应对高并发请求或突发连接请求的情况。
- 最大空闲连接数量(maxIdle): 指连接池中最大的空闲连接数,也就是连接池中最多允许保持的空闲连接数量。当连接池中的空闲连接数量达到了maxIdle设定的值后,多余的空闲连接将会被连接池释放掉。
- 最大等待时间(maxWait):当连接池中的连接数量达到最大值时,后续请求需要等待的最大时间,如果超过这个时间,则会抛出异常。
- 连接有效性检查(testOnBorrow、testOnReturn):为了确保连接池中只有可用的连接,一些连接池会定期对连接进行有效性检查,这里的属性就是配置这些检查的选项。
- 连接的driver、url、user、password等。
以上这些属性是连接池中较为常见的一些属性,不同的连接池在实现时可能还会有其他的一些属性,不过大多数连接池都包含了以上几个属性,对于使用者来说需要根据自己的需要进行灵活配置。
常用的连接池
市面上常用的数据库连接池有许多,以下是其中几种:
- DBCP
- 2001年诞生,最早的连接池。
- Apache Software Foundation的一个开源项目。
- DBCP的设计初衷是为了满足Tomcat服务器对连接池管理的需求。
- c3p0
- 2004年诞生
- c3p0是由Steve Waldman于2004年推出的,它是一个高性能、高可靠性、易配置的数据库连接池。c3p0能够提供连接池的容错能力、自动重连等功能,适用于高并发场景和数据量大的应用。
- Druid
- 2012年诞生
- Druid连接池由阿里巴巴集团开发,于2011年底开始对外公开,2012年正式发布。Druid是一个具有高性能、高可靠性、丰富功能的数据库连接池,不仅可以做连接池,还能做监控、分析和管理数据库,支持SQL防火墙、统计分析、缓存和访问控制等功能。
- HikariCP
- 2012年诞生
- HikariCP是由Brett Wooldridge于2012年创建的开源项目,它被认为是Java语言下最快的连接池之一,具有快速启动、低延迟、低资源消耗等优点。HikariCP连接池适用于高并发场景和云端应用。
- 很单纯的一个连接池,这个产品只做连接池应该做的,其他的不做。所以性能是极致的。相对于Druid来说,它更加轻量级。
- Druid连接池在连接管理之外提供了更多的功能,例如SQL防火墙、统计分析、缓存、访问控制等,适用于在数据库访问过程中,需要进行细粒度控制的场景
- HikariCP则更侧重于性能方面的优化,对各种数据库的兼容性也更好
- BoneCP
- 2015年诞生
- BoneCP是一款Java语言下的高性能连接池,于2015年由Dominik Gruntz在GitHub上发布。BoneCP具有分布式事务、连接空闲检查、SQL语句跟踪和性能分析、特定类型的连接池等特点。BoneCP连接池适用于大型应用系统和高并发的负载场景
连接池的使用
Druid的使用
第一步:引入Druid的jar包
第二步:配置文件
在类的根路径下创建一个属性资源文件:jdbc.properties
1 | url=jdbc:mysql://localhost:3306/jdbc |
第三步:编写代码,从连接池中获取连接对象
1 | // 读取属性配置文件 |
第四步:关闭连接
仍然调用Connection的close()方法,但是这个close()方法并不是真正的关闭连接,只是将连接归还到连接池,让其称为空闲连接对象。这样其他线程可以继续使用该空闲连接。
HikariCP的使用
第一步:引入jar包
第二步:编写配置文件
在类的根路径下创建一个属性资源文件:jdbc2.properties
1 | jdbcUrl=jdbc:mysql://localhost:3306/jdbc |
第三步:编写代码,从连接池中获取连接
1 | InputStream in = HikariConfig.class.getClassLoader().getResourceAsStream("config.properties"); |
第四步:关闭连接(调用conn.close(),将连接归还到连接池,连接对象为空闲状态。)