当前位置: 首页 > news >正文

21.数据库连接池

1.不同连接池的参数配置

  • HikariCP
<!-- 配置HikariCP数据源(连接池核心Bean) -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"><!-- 基础数据库配置 --><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><!-- 连接池核心参数(和之前讲的一一对应) --><property name="maxPoolSize" value="20"/>          <!-- 最大连接数 --><property name="minIdle" value="5"/>              <!-- 最小空闲连接 --><property name="connectionTimeout" value="3000"/> <!-- 获取连接超时3秒 --><property name="idleTimeout" value="600000"/>     <!-- 空闲10分钟回收 --><property name="maxLifetime" value="1800000"/>    <!-- 连接最长存活30分钟 --><property name="testWhileIdle" value="true"/>     <!-- 空闲时验证连接有效性 -->
</bean><!-- 配置JdbcTemplate(用连接池执行SQL) -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/> <!-- 关联上面的连接池 -->
</bean>
  • Druid
<!-- 配置Druid数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><!-- 基础数据库配置 --><property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><!-- 连接池核心参数 --><property name="maxActive" value="20"/>          <!-- 对应Hikari的maxPoolSize --><property name="minIdle" value="5"/>             <!-- 最小空闲连接 --><property name="maxWait" value="3000"/>          <!-- 获取连接超时3秒(对应connectionTimeout) --><property name="minEvictableIdleTimeMillis" value="600000"/> <!-- 空闲超时 --><property name="maxEvictableIdleTimeMillis" value="1800000"/> <!-- 最大生命周期 --><property name="testWhileIdle" value="true"/>    <!-- 空闲时验证 --><property name="validationQuery" value="SELECT 1"/> <!-- 验证连接的SQL(MySQL) -->
</bean><!-- 配置JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/>
</bean>
  • dbcp2
<!-- 配置DBCP2数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"><!-- 1. 基础数据库配置 --><property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><!-- 2. 连接池核心参数(对应之前的Hikari/Druid参数) --><property name="maxTotal" value="20"/>          <!-- 最大连接数(对应Hikari的maxPoolSize) --><property name="minIdle" value="5"/>            <!-- 最小空闲连接 --><property name="maxWaitMillis" value="3000"/>   <!-- 获取连接超时时间(3秒,对应connectionTimeout) --><property name="minEvictableIdleTimeMillis" value="600000"/> <!-- 空闲连接超时回收(10分钟) --><property name="maxConnLifetimeMillis" value="1800000"/>      <!-- 连接最大生命周期(30分钟) --><!-- 3. 连接验证配置 --><property name="testWhileIdle" value="true"/>   <!-- 空闲时验证连接有效性 --><property name="validationQuery" value="SELECT 1"/> <!-- 验证连接的SQL(MySQL) --><property name="validationQueryTimeout" value="1"/> <!-- 验证超时(1秒) -->
</bean><!-- 配置JdbcTemplate(关联DBCP2连接池) -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/>
</bean>

2.特别重要的一个参数----最大连接数、最小空闲数

  • 传统的 DBCP 设计成动态的(minIdle < maxTotal),是为了省内存。
    没人用的时候,我只维护 5 个连接,省点 RAM。人多了,我再临时 new Connection() 涨到 20 个。

  • 现代的最佳实践变了(HikariCP 的理念):
    现在的服务器内存都很大,不差这几个连接的内存。所以 HikariCP 建议: minIdle = maxTotal
    也就是说:一上来就铺满 20 张桌子,永远不撤。
    好处: 来了客人直接坐,不需要临时去搬桌子(不需要临时建立 TCP 连接),响应最快,性能最稳。

  • 核心性能悖论:那为啥连接设很大会出现性能反而很低呢?

    操作系统(CPU 调度器)的做法: 为了公平,它不能让某个人一直占着cpu,于是它强制实行“轮班制”。
    假设cpu只有4核,但是你允许的连接数是1000,故而高并发的话,会导致1000个线程同时工作,导致cpu高频切换,cpu切换的代价也是很高的,频繁的切换导致了用于切换线程的开销(保存和恢复现场)远远高于线程正正干活的开销,故而导致性能远远下降。

    • 黄金经验公式(针对机械硬盘):\(连接数 = (CPU核心数 \times 2) + 1\)

    • 如果是 SSD 硬盘: 因为读写极快,CPU 等待时间变短,公式甚至可以接近 CPU核心数

      为什么?按照常理,设备越快,应该能处理越多的连接才对,为什么 SSD 越快,我们需要的并发连接数反而越少(越接近 CPU 核数) 呢?

      有一个经典的线程数计算公式:$$最佳线程数 = CPU核数 \times \left( 1 + \frac{等待时间 (I/O)}{计算时间 (CPU)} \right)$$

      公式里的 \(\frac{等待时间}{计算时间}\) 趋近于 0,最佳线程数 趋近于CPU核数。

    总结
    越慢的 I/O (HDD): CPU 休息时间越多 -> 需要越多备胎(连接)来填补空缺 -> 连接数要大。
    越快的 I/O (SSD/内存): CPU 休息时间越少 -> 原来的线程一个人就能把 CPU 跑满 -> 不需要备胎 -> 连接数越少(接近核数)。

3.结尾---连接池返回给我们的connetion对象
本质是代理对象,但是在dbcp连接池中,并没有使用JDK原生代理,而是重新实现了 java.sql.Connection 接口,长得和普通连接一模一样(这个实现类被称为代理类,持有connetion原始对象的引用),许多功能是直接使用原始connetion对象的,但是对于 conn.close() 此时并不是关闭物理连接(这里的close是被修改过逻辑的,不可能让你直接就去把连接给关闭了),只是将当前的connetion对象引用归还给连接池。

http://www.gsyq.cn/news/94596.html

相关文章:

  • 放过自己,也放过你的领导
  • Part 03|当客户真的要交付时,我最先考虑的不是技术
  • 我对防抖(Debounce)的一点理解与实践:从基础到立即执行
  • [网鼎杯 2020 青龙组]AreUSerialz(个人记录写题笔记,含PHP反序列化的原理、漏洞成因以及利用技巧)
  • Comsol Multiphysics数值模拟
  • 战网注册后显示无法登录
  • PINBAI平板电脑维修实例
  • 13. django中间件
  • 人工智能之数学基础:离散条件分布和连续条件概率密度
  • 精通 Flutter 网络请求:从基础 GET/POST 到拦截器 + 缓存 + 断点续传的全维度实践
  • 前端最新技术,零基础入门到精通,收藏这篇就够了
  • 前端失业有多严重?
  • 第二章-依赖属性
  • ARM 架构中的数据内存屏障指令 DMB
  • TileLang终极指南:45分钟内打造你的首个高性能GPU算子
  • 窗口相关操作的总结
  • 北京陪诊服务权威推荐榜单 - 品牌排行榜单
  • 2026中专毕业想做出纳,考哪些证书企业比较认可?这些证让你轻松入职!
  • 峰值检测电路
  • 量子计算驱动的分布式云存储系统在数据安全与高效检索中的创新应用 - 教程
  • 从零到一:构建一个实时语音翻译应用(Vue3 + Web Speech API)
  • 基于PyTorch的深度学习基础课程之十:损失函数
  • Spark:革命性的命令行数据可视化工具,让DevOps监控更高效
  • 基于Java的安全生产智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 基于Java的安全生产智经营理系统的设计与实现全方位解析:附毕设论文+源代码
  • 基于Java的安全生产检查统计分析智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 3步打造Switch专属开机动画:让你的主机从启动就与众不同
  • 北京上门收画服务权威推荐榜单​ - 品牌排行榜单
  • 重练算法(代码随想录版) day39 - 动态规划part7
  • LLM - 从 Prompt 到上下文工程:面向 Java 的生产级 AI Agent 设计范式