数据库连接池的原理没你想得这么复杂

来源 | 犀牛饲养员的技术笔记

封图| CSDN 下载于视觉中国

背景介绍

数据库连接池和线程池等池技术存在的意义都是为了解决资源的重复利用问题。在计算机里,创建一个新的资源往往开销是非常大的。而池技术可以统一分配,管理某一类资源,它允许我们的程序可以重复的使用这个资源,只有在极端情况下(比如连接池满)才会创建新的资源。

数据库连接这种资源尤其昂贵,它的创建开销很大,大量的创建连接和释放操作对程序的影响非常明显。

数据库连接池正是针对这个问题提出来的。

实现原理

需要注意的是,我们下面提供的几种实现方式都是基于简单的原型,目的是带你了解连接池实现的一些基本原理。真实的数据库连接池技术需要考虑更多复杂的细节。

所以下面这些代码都是不能在生产上直接使用的

实现的时候会用到java.sql.Connection,由于这个只是一个接口无法创建实例,为了演示方便,我继承这个接口写了一个简单的测试类,只是在commit方法里加了延时模拟提交。

实现方式1:

很容易马上想到的一种方案,我们用一个map存放连接对象,需要的时候从map里拿来用就可以了。

这里需要注意,尽管我们使用了线程安全的ConcurrentHashMap来存放连接资源,getConnection方法依然要加上synchronized关键字来避免并发问题。这一点是最容易忽略的。

试想一下,假设在某个场景下,我们希望某个应用的多个线程共享连接资源。

假设有2个线程同时执行到了pool.containsKey(key),然后都返回false,那这两个线程都会创建连接。虽然ConcurrentHashMap的put方法只会加入其中一个,但还是生成了1个多余的连接。

原因在于,尽管ConcurrentHashMap本身每个操作都是线程安全的,但是当这些操作组合在一起使用的时候,就无法保证原子性了,所以有可能带来并发的问题。

这里友情提示下,面试经常会遇到这个考点哦。

实现方式 2:

第二种实现方式是在1的基础上进行的优化。1的方案有个问题就是每次访问getConnection都要加锁,释放锁,效率比较低。

第二种方案是利用java并发包里的Future机制来解决并发场景创建多余连接的问题。


我们来捋一捋这个实现会不会有并发的问题。假设两个线程同时进入else分支,在代码的28行ConcurrentHashMap可以确保只有一个线程会执行,也就是只会加入一个task。其它的线程都不会加入成功。

所以只有一个线程connectionFutureTask == null,这个线程开始异步执行创建连接的任务,而其它的线程则会调用FutureTask的get方法直接获取结果。

实现方式3:

1和2的实现方式还存在一个问题, 多个线程获取到的其实同一个连接。这种方案在某些场景下是不允许的。比如spring数据库的事务管理器对于每个事务的处理线程都要求独立的连接资源。

下面的方案基于链表结构,有比较完整的获取,释放的操作,不同的线程可以拿到独立的连接资源。


注意到这个方案我们在获取连接的时候引入了超时时间,如果该方法能够在一段时间内获取到结果,那么将结果立刻返回,反之,超时返回默认结果。

druid连接池的实现原理

了解了实现连接池的大概思路,我们可以来继续学习下市面上比较成熟的连接池产品。这其中阿里巴巴开源的druid开源连接池就是一个代表。

Druid作为java领域最好的连接池技术之一,连接池本身只是它的一部分功能。除此之外,它还还要配套的监控功能。当然这个不是我们本文的重点。

先来看看在代码中如何使用Druid连接池,

所以继续深入到是DataSource里的getConnection方法,

init方法主要的功能是根据配置文件初始化连接池,它内部会生成一些真正的物理连接然后放入一个数组里。当然这个方法要保证只会被调用一次。

继续往下看,最终会调用到getConnectionInternal这个私有方法,


红色圈出的部分是核心,根据传入的等待时间走不同的分支,我们来看看takeLast方法。


代码逻辑也比较清楚,poolCount是连接池的目前的可用连接数量。

如果为0,就通过emptySignal唤醒生产者线程创建新的连接,同时当前线程挂起等待notEmpty的信号。notEmptyWaitCount维护的就是正在等待的消费者数量。

如果不为0,就从数组中取出最后一个连接返回。有人可能会有疑问,这里返回的是DruidConnectionHolder,不是Connection啊?

其实看下前者的定义你就明白了,


DruidConnectionHolder封装了Connection以及连接的datasource信息,还有多个statement等,方面进行统一管理。

参考

  • 《java并发编程的艺术》

  • https://www.cnblogs.com/cz123/p/7693064.html

推荐阅读:Docker 开发环境的滑坡
2020年边缘计算最新前沿报告:如何与核心云、5G、AI协同?如何打造新业态和部署运营?
教你用 Android 做二次开发,识别率达到科大讯飞语音输入水平 | 原力计划
比特币Logo背后有哪些历史及象征意义?Logo 上的“B”为什么会向右倾斜?
了解这4个重点,带你探索未来将如何设计智能系统和机器人!
苹果阻止上架的这款软件,到底有多可恶?
真香,朕在看了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CICD联动阿里云容器服务Kubernetes实践之Bamboo篇

本文档以构建一个 Java 软件项目并部署到 阿里云容器服务的Kubernetes集群 为例说明如何使用 Bamboo在阿里云Kubernetes服务上运行Remote Agents并在agents上运行Build Plans。 1. 源码项目 本示例中创建的GitHub源码项目地址为: https://github.com/AliyunConta…

Python之%s%d%f使用实例

%s 字符串 string"hello" #%s打印时结果是hello print "string%s" % string # output: stringhello #%2s意思是字符串长度为2,当原字符串的长度超过2时,按原长度打印,所以%2s的打印结果还是hello pri…

Java关键字—instanceof

instanceof 是 Java 的一个二元操作符&#xff0c;类似于 &#xff0c;>&#xff0c;< 等操作符&#xff0c; 是 Java 的保留关键字。左边是对象&#xff0c;右边是类&#xff1b;当对象是右边类或者子类所创建的对象时&#xff0c;返回true&#xff0c;否则返回false。 …

拔掉数据库的电源会怎样?阿里云数据库新型灾备架构,让云端容灾有“备”无患

拔掉数据库的电源会怎样&#xff1f; 假设我们拔掉数据库的电源会怎样&#xff1f; 在日前举行的阿里云“企业级”云灾备解决方案发布会上&#xff0c;阿里云智能技术战略总监陈绪就来了一场现场“断电”演示&#xff0c;拔掉了数据库的电源。 &#xff08;直播回放&#xf…

docker --restart=always 参数 docker重启容器自动重启

创建容器时添加参数 --restartalways 后&#xff0c;当 docker 重启时&#xff0c;容器自动启动。 使用方法&#xff1a; docker container update --restartalways 容器名字操作实例如下&#xff1a; [rootlocalhost mnt]# docker ps -a CONTAINER ID IMAGE …

高可用 kubernetes 集群部署实践

前言 Kubernetes&#xff08;k8s&#xff09; 凭借着其优良的架构&#xff0c;灵活的扩展能力&#xff0c;丰富的应用编排模型&#xff0c;成为了容器编排领域的事实标准。越来越多的企业拥抱这一趋势&#xff0c;选择 k8s 作为容器化应用的基础设施&#xff0c;逐渐将自己的核…

还不知道 AWS 是什么?这 11 个重点带你认识 AWS !

作者 | Sajan Agrawal译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国云计算的出现使软件行业受益匪浅。大多数公司已经改变了策略&#xff0c;将现有的项目转移到云上&#xff0c;并在此基础上构建新的项目。今天&#xff0c;让我们了解一个名为亚马逊网络服务云&…

sql中count(1)、count(*)和count(字段名)的区别

执行效果上&#xff1a; count(*)包括了所有的列&#xff0c;相当于行数&#xff0c;在统计结果的时候&#xff0c;不会忽略列值为NULL。 count(1)包括了忽略所有列&#xff0c;用1代表代码行&#xff0c;在统计结果的时候&#xff0c;不会忽略列值为NULL 。 count(列名)只包…

KeeperErrorCode = Unimplemented for /test

使用Curator时报错&#xff0c;原因是因为版本问题 zookeeper版本&#xff1a;zookeeper-3.4.8 cuartor版本&#xff1a;3.2.0 看Curator官网的声明&#xff1a; 地址&#xff1a;http://curator.apache.org/ The are currently two released versions of Curator, 2.x.x and 3…

移动研发 DevOps 落地实践

传统的研发模式已经无法适应企业在数字化转型中快速迭代以及研发协同的要求&#xff0c;建设符合业务场景特性和有效支撑高并发、持续迭代集成需求的研发效能实践迫在眉睫。 本文将围绕支付宝如何随着移动市场的高速发展&#xff0c;逐步沉淀优化出适用业务发展需求的研发效能实…

Java-用户交互Scanner

next方式 public class Demo01 {public static void main(String[] args) {// 创建一个 扫描器对象&#xff0c;用于接收键盘数据Scanner scanner new Scanner(System.in);System.out.println("使用next 方式接收&#xff1a;");// 判断用户有没有输入字符串if (sc…

【ECS最佳实践】基于多块云盘构建LVM逻辑卷

一、LVM简介 LVM是逻辑盘卷管理&#xff08;Logical Volume Manager&#xff09;的简称&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制&#xff0c;LVM是建立在硬盘和分区之上的一个逻辑层&#xff0c;来提高磁盘分区管理的灵活性。 LVM最大的特点就是可以对磁盘进行…

剧情反转:今年AI要凉!薪资碾压全行,但人才缺500万!

最近关于AI有两个消息&#xff0c;一个好的&#xff0c;一个坏的。先说好消息。德勤发布《全球人工智能发展白皮书》&#xff0c;预计到2025年&#xff0c;世界人工智能市场规模将超过6万亿美元&#xff01;2017年至2025年复合增长率达30%。毫无疑问&#xff0c;目前AI还是一个…

主索引频繁分裂

问题描述&#xff1a; 每个数据页都会为存储在它里边儿的记录生成一个页目录&#xff0c;在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽&#xff0c;然后再遍历该槽对应分组中的记录即可快速找到指定的记录&#xff0c;如果主键不是id单调递增的,有…

maven 报错一站式解决方案

文章目录一、本地maven玩耍三部曲1. 先确认项目引用默认的maven配置是否正确2. 查看IntelliJ IDEA查看maven配置是否正确3. 重新导入maven依赖二、本地maven报错5步走2.1. 配置maven阿里云仓库2.2. 删除本地仓库中不完整的jar2.3. 连接外网2.4. 在线下载依赖2.5. 重新导入maven…

如果测试没有梦想,那跟咸鱼有什么区别?

软件质量不是测出来的&#xff0c;但为什么又有这么多测试工程师为了质量而工作&#xff1f;测试是一个成本部门&#xff0c;测试创造的价值是什么&#xff1f;研发的模式在不断地变化&#xff0c;测试的定位如何不断去定义&#xff0c;未来的测试又会是什么形态&#xff1f;今…

Java-Scanner进阶使用

整数、小数 输入 public class Demo04 {public static void main(String[] args) {Scanner scanner new Scanner(System.in);// 从键盘接收数据int i 0;float f 0.0f;System.out.println("请输入整数&#xff1a; ");if (scanner.hasNextInt()){i scanner.nextI…

使用阿里云极速型NAS构建高可用的GitLab

使用阿里云文件存储NAS构建GitLab高可用环境 GitLab简介 GitLab是一个利用 Ruby on Rails 开发的开源应用程序&#xff0c;实现一个自托管的Git项目仓库&#xff0c;可通过Web界面进行访问公开的或者私人项目。Ruby on Rails 是一个可以使你开发、部署、维护 web 应用程序变得…

The following SDK components were not installed: extra-google-m2repository and platform-tools

安装android studio到最后一步的时候遇见了这个问题 。 android studio安装详见Android Studio 安装 经过查阅多篇博客 把他们的解决方案放在一起一顿操作猛如虎&#xff0c;然后就成了。。。 2篇原文链接我放在这里&#xff1a; Android Studio新建工程时SDK缺少extra-an…

数据库中间件漫谈——看看云时代,它会走向何方

来源 | 阿丸笔记封图| CSDN 下载于视觉中国前言随着业务的发展&#xff0c;MySQL数据库中的表会越来越多&#xff0c;表中的数据量也会越来越大&#xff0c;相应地&#xff0c;数据操作的开销也会越来越大&#xff1b;另外&#xff0c;无论怎样升级硬件资源&#xff0c;单台服务…