池化技术-你真的熟悉数据库连接池吗?手写实现连接池


目录

一、数据库连接池简介

1、what? 什么池?

2、where? 在哪里应用?

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

4、数据库连接池的优点

5、连接池与jdbc的关系

6、基本功能

7、设计思路

二、应用实战

1、SpringBoot应用

2、依赖

3、jdbc工具类

4、连接池接口定义

5、具体实现

6、Controller

7、业务逻辑类

8、测试

往期推荐


引言

对于有几年后端开发经验的程序员而言,或多或少都有使用过数据库连接池,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 优化

// 存活的连接数,一开始默认0
private 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表数据清空

(2)启动应用,浏览器访问 localhost:8080/test?times=10 地址20次(快速点击20次),输出结果:

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

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

参考资料:

享学课堂公开课

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

往期推荐

史上最强Tomcat8性能优化

日均5亿查询量的京东到家订单中心,为什么舍MySQL用ES?

四张图带你了解Tomcat系统架构--让面试官颤抖的Tomcat回答系列!

“12306”架构到底有多牛逼--秒杀系统的艺术

阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路

B2B电商平台--ChinaPay银联电子支付功能

学会Zookeeper分布式锁,让面试官对你刮目相看

SpringCloud电商秒杀微服务-Redisson分布式锁方案

一只 有深度 有灵魂 的公众号0.0

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值