你真的熟悉数据连接池吗?手写实现连接池

Posted 阿甘正专

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的熟悉数据连接池吗?手写实现连接池相关的知识,希望对你有一定的参考价值。

点击关注“阿甘正专”,设为星标

奇迹每天都在发生,等你而来

你真的熟悉数据连接池吗?手写实现连接池



引言

对于有几年后端开发经验的程序员而言,或多或少都有使用过数据库连接池,jdbc也是老生常谈,但是很多人或许仅是停留在会使用,至于 底层是怎么实现的、为何要使用它、不使用它是否可以、什么场景下使用它等 也不会去深入了解,反正是在搭好的框架上开发,别人这么配,我也跟着配,配置好数据库连接,专注于业务逻辑开发即可,仅止步于数据库的增删改查。




一、数据库连接池简介


1、what? 什么池?

简单来说,就是提前创建保存大量的资源(对象),以备不时之需

常见池化技术:

  • 线程池:管理线程对象的池

  • 对象池:初始化一些对象的池,如jdk的静态常量池、运行时常量池等

  • 连接池:管理连接对象的池

你真的熟悉数据连接池吗?手写实现连接池

常见:

  • 1、C3PO-开源连接池,Hibernate,Spring

  • 2、BonecP--apache出品tomcat使用

  • 3、Druid--阿里出品,史上最强没有之一,对所有sql的监控

  • 4、HikaricP--springboot2,java最快连接池


2、where? 在哪里应用?

资源的合理管理与分配,多个应用连接同一个数据库时,更不能因为某个应用独占所有的资源连接,导致其他应用无法提供服务。

你真的熟悉数据连接池吗?手写实现连接池

什么东西需要池化技术?

  • 有限资源-数据库连接,计划分配,资源管控,减少开销

  • 开销大/耗时-线程池,开辟栈空间,创建/销毁开销大


场景(运营)需求:

  • 1、管理mysql连接

  • 2、200并发量

  • 3、MySQL Pool最大连接数为10---限流

  • 4、服务对象维护


3、数据库连接池的实现及原理

注:一些原理及概念的文字,不想看的直接跳过到实战应用,摘自

https://blog.csdn.net/wangjunjie0817/article/details/89380841

对于一个简单的数据库应用,由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用,情况就完全不同了。频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈。
连接复用
通过建立一个数据库连接池以及一套连接使用管理策略,使得一个数据库连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。
资源池:
对于共享资源,有一个很著名的设计模式: 资源池
该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,就是建立一个数据库连接池,提供一套高效的连接分配、使用策略,最终目标是实现连接的高效、安全的复用。
基本原理
在内部对象池中维护一定数量的数据库连接,并对外暴露数据库连接获取和返回方法。如:外部使用者可通过getConnection方法。
方法获取连接,使用完毕后再通过releaseConnection 方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。


4、数据库连接池的优点

  • 资源重用

  • 更快的系统响应速度

  • 新的资源分配手段

  • 统一的连接管理,避免数据库连接泄漏


5、连接池与jdbc的关系

JDBC连接池 在标准JDBC对应用的接口中,并没有提供资源的管理方法。所以,缺省的资源管理由应用自己负责。虽然在JDBC规范中,多次提及资源的关闭/回收及其他的合理运用。但最稳妥的方式,还是为应用提供有效的管理手段。所以,JDBC为第三方应用服务器(Application Server)提供了一个由数据库厂家实现的管理标准接口:连接缓冲(connection pooling)。引入了连接池( Connection Pool )的概念 ,也就是以缓冲池的机制管理数据库的资源。

JDBC最常用的资源有三类:

  • Connection: 数据库连接

  • Statement: 会话声明

  • ResultSet: 结果集游标

这是一种“爷—父—子”的关系,对Connection的管理,就是对数据库资源的管理。

举个例子: 如果想确定某个数据库连接(Connection)是否超时,则需要确定其(所有的)子Statement是否超时,同样,需要确定所有相关的 ResultSet是否超时;在关闭Connection前,需要关闭所有相关的Statement和ResultSet。因此,连接池(Connection Pool)所起到的作用,不仅仅简单地管理Connection,还涉及到 Statement和ResultSet。


6、基本功能

  • 初始化:预先创建好对象,放入池中

  • 设定最大数,防止无尽连接,资源耗尽

  • 客户端从池中出借空闲连接对象

  • 客户端归还连接对象回池

  • 体检-自我检测

你真的熟悉数据连接池吗?手写实现连接池


7、设计思路

(1)获取连接 getConnect()

  • 从idle中取出对象,放入busy

  • Idle有值,直接取

  • ldle无值,若池子未满,新建

  • 池满全繁忙,等待返还

(2)释放连接 releaseConnect()

  • 从繁忙工作队列中移除对象,放入空闲队列中

你真的熟悉数据连接池吗?手写实现连接池


二、应用实战


1、SpringBoot应用

新建一个SpringBoot应用:mini-pool

你真的熟悉数据连接池吗?手写实现连接池


2、依赖

maven 主要依赖,jdbc连接mysql的驱动

你真的熟悉数据连接池吗?手写实现连接池


3、jdbc工具类

新建一个创建jdbc连接的工具类

注:实际项目中,配置信息要填写在配置文件中,这里为了方便演示,就直接写死再代码中了。


你真的熟悉数据连接池吗?手写实现连接池


4、连接池接口定义

新增一个 MiniPool 简单的连接池接口,包含如下方法:初始化、销毁连接、获取连接、释放连接等

你真的熟悉数据连接池吗?手写实现连接池


5、具体实现

MiniPoolImpl 实现 MiniPool接口方法

@Slf4j
public class MiniPoolImpl implements MiniPool {
// 空闲连接队列
private LinkedBlockingQueue<Connection> idleQueue;
// 工作中队列
private LinkedBlockingQueue<Connection> busyQueue;
// 连接池最大数量
private final int maxSize;
// 存活的连接数,一开始默认0
private AtomicInteger activeSize = new AtomicInteger(0);
public
MiniPoolImpl(int maxSize){
this.maxSize = maxSize;
}
/**
*
初始化连接池
*/
@Override
public void init() {
idleQueue = new LinkedBlockingQueue<Connection>();
busyQueue = new LinkedBlockingQueue<Connection>();
}
/**
*
销毁
*/
@Override
public void destory() {
}

其中,释放连接方法:

你真的熟悉数据连接池吗?手写实现连接池

主要是获取连接方法:

  • (1)判断空闲队列是否有值,有直接取返回

  • (2)若空闲队列无值,而且连接池未满,则新建一个连接

  • (3)连接池全繁忙工作中,阻塞等待一定时间返回


你真的熟悉数据连接池吗?手写实现连接池

其中,第2步同步代码块部分,可使用原子类 AtomicInteger 优化

// 存活的连接数,一开始默认0private AtomicInteger activeSize = new AtomicInteger(0);

你真的熟悉数据连接池吗?手写实现连接池

注意:

  • activeSize.get()   获取当前活跃连接数

  • activeSize.incrementAndGet()   先加1再获取(原子操作)

这里,因为 activeSize.incrementAndGet()  activeSize.get()  性能高,所以双重判断比只用 activeSize.incrementAndGet() 判断好,锁的双重判断


配置注册到Spring容器管理:

你真的熟悉数据连接池吗?手写实现连接池


6、Controller

编写测试类Controller,新增一个http接口方法,便于发送http请求

你真的熟悉数据连接池吗?手写实现连接池


7、业务逻辑类

具体的业务逻辑测试类,因为要模拟200并发访问,使用多线程技术模拟,业务处理只是简单地往数据库插入200条数据,主要是观察日志输出,是否有需要排队等待获取连接的情况,最好是打断点观察。

注:这里为了简单测试,就不写接口了。

你真的熟悉数据连接池吗?手写实现连接池


8、测试

(1)t_user表数据清空

你真的熟悉数据连接池吗?手写实现连接池

你真的熟悉数据连接池吗?手写实现连接池

你真的熟悉数据连接池吗?手写实现连接池

你真的熟悉数据连接池吗?手写实现连接池

从日志中,可以看到,在数据库连接池最大数量配置为10个,200并发访问时,有部分需要排队等待获取连接。

(3)查看数据库,已经成功插入200条数据

你真的熟悉数据连接池吗?手写实现连接池


参考资料:

享学课堂公开课

https://blog.csdn.net/wangjunjie0817/article/details/89380841

你真的熟悉数据连接池吗?手写实现连接池

一只 有深度 有灵魂 的公众号0.0你真的熟悉数据连接池吗?手写实现连接池

你真的熟悉数据连接池吗?手写实现连接池

右上角按钮分享给更多人哦~你真的熟悉数据连接池吗?手写实现连接池

来都来了,点个在看再走吧~~~



以上是关于你真的熟悉数据连接池吗?手写实现连接池的主要内容,如果未能解决你的问题,请参考以下文章

面试官:了解数据库连接池吗?

mongodb如何管理连接的?有必要实现连接池吗

你真的知道如何设置数据库连接池的大小吗

spark streaming可以基于executor建立mysql的连接池吗

C语言有mysql数据库连接池吗?

Android:Firebase 实时数据库有连接池吗?