数据库连接池大小设置,你学会了吗

简介: 数据库连接池大小设置,你学会了吗

背景


工作这么多年,数据库连接池用了很久了,但是前几天突然被同事问到:“数据库连接池的大小怎么配?”,突然感觉心里慌的一逼,作为这么多年编程经验的老鸟,绝逼不能承认说自己不会,只能淡定的说:测试环境并发少,巴拉巴拉……,所以可以配置少点;生产环境并发高,所以数据库连接池的连接数要配置的多点。然后在小弟崇拜的眼神中,赶紧偷溜。

我是绝逼不会说,自己是百度复制粘贴,一顿操作猛如虎,一看并发150的。


回到正题,那么数据库连接池的大小究竟该怎么设置呢?


资源分析


当我们寻找数据库的性能瓶颈时,总是可以将其归为三类:CPU、磁盘、网络。把内存加进来也没有错,但比起磁盘和网络,内存的带宽要高出好几个数量级,所以就先不加了。


如果我们无视磁盘和网络,那么结论就非常简单。在一个8核的服务器上,设定连接/线程数为8能够提供最优的性能,再增加连接数就会因上下文切换的损耗导致性能下降。数据库通常把数据存储在磁盘上,磁盘又通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。读/写头同一时刻只能出现在一个地方,然后它必须“寻址”到另外一个位置来执行另一次读写操作。所以就有了寻址的耗时,此外还有旋回耗时,读写头需要等待碟片上的目标数据“旋转到位”才能进行操作。使用缓存当然是能够提升性能的,但上述原理仍然成立。


在这一时间段(即"I/O等待")内,线程是在“阻塞”着等待磁盘,此时操作系统可以将那个空闲的CPU核心用于服务其他线程。所以,由于线程总是在I/O上阻塞,我们可以让线程/连接数比CPU核心多一些,这样能够在同样的时间内完成更多的工作。


那么应该多多少呢?

这要取决于磁盘。较新型的SSD不需要寻址,也没有旋转的碟片。可别想当然地认为“SSD速度更快,所以我们应该增加线程数”,恰恰相反,无需寻址和没有旋回耗时意味着更少的阻塞,所以更少的线程[更接近于CPU核心数]会发挥出更高的性能。只有当阻塞创造了更多的执行机会时,更多的线程数才能发挥出更好的性能。


网络和磁盘类似。通过以太网接口读写数据时也会形成阻塞,10G带宽会比1G带宽的阻塞少一些,1G带宽又会比100M带宽的阻塞少一些。不过网络通常是放在第三位考虑的,有些人会在性能计算中忽略它们。


线程数设置多少,核心是分析CPU数目以及请求执行过程中哪些地方会堵塞耗时等因素之间的权衡;

比如都是CPU计算的任务,那么增大线程数对提高整体速度是没有用处的。


线程公式


下面的公式是由PostgreSQL提供的,不过我们认为可以广泛地应用于大多数数据库产品。你应该模拟预期的访问量,并从这一公式开始测试你的应用,寻找最合适的连接数值。


连接数 = ((核心数 * 2) + 有效磁盘数)


按这个公式,你的4核i7数据库服务器的连接池大小应该为((4 * 2) + 1) = 9。取个整就算是是10吧。是不是觉得太小了?跑个性能测试试一下,我们保证它能轻松搞定3000用户以6000TPS的速率并发执行简单查询的场景。如果连接池大小超过10,你会看到响应时长开始增加,TPS开始下降。


扩展说明:

这一公式其实不仅适用于数据库连接池的计算,大部分涉及计算和I/O的程序,线程数的设置都可以参考这一公式。我之前在对一个使用Netty编写的消息收发服务进行压力测试时,最终测出的最佳线程数就刚好是CPU核心数的一倍。


公理:你需要一个小连接池,和一个充满了等待连接的线程的队列


如果你有10000个并发用户,设置一个10000的连接池是非常不明智的。1000仍然很恐怖。即是100也太多了。你需要一个10来个连接的小连接池,然后让剩下的业务线程都在队列里等待。连接池中的连接数量应该等于你的数据库能够有效同时进行的查询任务数(通常不会高于2*CPU核心数)。


我们经常见到一些小规模的web应用,应付着大约十来个的并发用户,却使用着一个100连接数的连接池。这会对你的数据库造成极其不必要的负担。


请注意:


连接池的大小最终与系统特性相关。

比如一个混合了长事务和短事务的系统,通常是任何连接池都难以进行调优的。最好的办法是创建两个连接池,一个服务于长事务,一个服务于短事务。


再例如一个系统执行一个任务队列,只允许一定数量的任务同时执行,此时并发任务数应该去适应连接池连接数,而不是反过来。


HikariCP连接池推荐配置


<!-- Hikari Datasource -->
 <bean id="dataSourceHikari" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="shutdown">
  <!-- <property name="driverClassName" value="${db.driverClass}" /> --> <!-- 无需指定,除非系统无法自动识别 -->
  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />
  <property name="username" value="${db.username}" />
  <property name="password" value="${db.password}" />
   <!-- 连接只读数据库时配置为true, 保证安全 -->
  <property name="readOnly" value="false" />
  <!-- 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒 -->
  <property name="connectionTimeout" value="30000" />
  <!-- 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟 -->
  <property name="idleTimeout" value="600000" />
  <!-- 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';) -->
  <property name="maxLifetime" value="1800000" />
  <!-- 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count) -->
  <property name="maximumPoolSize" value="15" />
 </bean>


细心的读者可能发现,这里没有配置minimumIdle参数,这是因为如果minimumIdle小于maximumPoolSize,HikariCP将竭尽全力快速有效地添加其他连接。但是,为了获得最佳性能和对峰值需求的响应能力,我们建议不要设置此值,而应让HikariCP充当固定大小的连接池。

这点可以类比jvm参数中,Xms和Xmx一般推荐设置的一样,这样可以减轻程序运行过程中堆伸缩带来的压力。


https://github.com/brettwooldridge/HikariCP


minimumIdle

This property controls the minimum number of idle connections that HikariCP tries to maintain in the pool. If the idle connections dip below this value and total connections in the pool are less than maximumPoolSize, HikariCP will make a best effort to add additional connections quickly and efficiently. However, for maximum performance and responsiveness to spike demands, we recommend not setting this value and instead allowing HikariCP to act as a fixed size connection pool. Default: same as maximumPoolSize


最后


牢记数据库连接池的计算公式:

                  连接数 = ((核心数 * 2) + 有效磁盘数)

根据资源使用,线程等待时间分析公式的合理性。

另外最大连接数和最小连接数设置相等

目录
相关文章
|
1月前
|
DataWorks NoSQL 关系型数据库
DataWorks常见问题之鉴权数据库设置失败如何解决
DataWorks是阿里云提供的一站式大数据开发与管理平台,支持数据集成、数据开发、数据治理等功能;在本汇总中,我们梳理了DataWorks产品在使用过程中经常遇到的问题及解答,以助用户在数据处理和分析工作中提高效率,降低难度。
|
1月前
|
数据库 索引 OceanBase
OceanBase数据库设置了二级索引,但查看执行计划,没有反应出来,这种情况是为什么呢?
OceanBase数据库设置了二级索引,但查看执行计划,没有反应出来,这种情况是为什么呢?【1月更文挑战第12天】【1月更文挑战第60篇】
96 2
|
8月前
|
数据库连接 数据库 Android开发
Android -- Room简化数据库设置图书案例
Android -- Room简化数据库设置图书案例
30 0
|
11天前
|
SQL Oracle 关系型数据库
|
1月前
|
关系型数据库 MySQL 数据库
mysql添加用户并设置数据库权限
mysql添加用户并设置数据库权限
|
1月前
|
关系型数据库 MySQL 数据库
mysql 设置环境变量与未设置环境变量连接数据库的区别
设置与未设置MySQL环境变量在连接数据库时主要区别在于命令输入方式和系统便捷性。设置环境变量后,可直接使用`mysql -u 用户名 -p`命令连接,而无需指定完整路径,提升便利性和灵活性。未设置时,需输入完整路径如`C:\Program Files\MySQL\...`,操作繁琐且易错。为提高效率和减少错误,推荐安装后设置环境变量。[查看视频讲解](https://www.bilibili.com/video/BV1vH4y137HC/)。
103 3
mysql 设置环境变量与未设置环境变量连接数据库的区别
|
19天前
|
存储 SQL 缓存
Java性能优化(十)-数据库调优-数据库参数设置优化
Java性能优化(十)-数据库调优-数据库参数设置优化
23 0
|
1月前
|
DataWorks 安全 数据库
DataWorks产品使用合集之在DataWorks中,使用Power BI Desktop来连接Hologres数据库需要设置白名单如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
59 2
|
1月前
|
运维 分布式计算 DataWorks
DataWorks产品使用合集之dataworks为子账号创建DataWorks访问密钥的基本步骤如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
36 0
|
1月前
|
关系型数据库 MySQL 数据库
mysqwl 数据库 设置默认时间 datetime 和 timestamp 实测
mysqwl 数据库 设置默认时间 datetime 和 timestamp 实测
22 0

热门文章

最新文章