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

微信公众号:跟着老万学java
关注可了解更多的开发技巧。问题或建议,请公众号留言;java

背景

工做这么多年,数据库链接池用了好久了,可是前几天忽然被同事问到:“数据库链接池的大小怎么配?”,忽然感受内心慌的一逼,做为这么多年编程经验的老鸟,绝逼不能认可说本身不会,只能淡定的说:测试环境并发少,巴拉巴拉……,因此能够配置少点;生产环境并发高,因此数据库链接池的链接数要配置的多点。而后在小弟崇拜的眼神中,赶忙偷溜。
我是绝逼不会说,本身是百度复制粘贴,一顿操做猛如虎,一看并发150的。mysql

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

资源分析

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

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

在这一时间段(即"I/O等待")内,线程是在“阻塞”着等待磁盘,此时操做系统能够将那个空闲的CPU核心用于服务其余线程。因此,因为线程老是在I/O上阻塞,咱们可让线程/链接数比CPU核心多一些,这样可以在一样的时间内完成更多的工做。sql

那么应该多多少呢?
这要取决于磁盘。较新型的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) + 有效磁盘数)
根据资源使用,线程等待时间分析公式的合理性。
另外最大链接数和最小链接数设置相等。

恭喜看完本篇,是否是忽然有种想出去装逼的冲动。去吧,少年,学习知识就是这么快乐。

参考:
https://www.jianshu.com/p/15b846107a7c
https://github.com/brettwooldridge/HikariCP


更多精彩,关注我吧。




本文分享自微信公众号 - 跟着老万学java(douzhe_2019)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索