数据库连接池浅析
本文由 ImportNew - hejiani 翻译自 javacodegeeks。欢迎加入Java小组。转载请参见文章末尾的要求。
简介
我从事的所有项目都用到了数据库连接池,这样做自然有它的理由。有时我们可能忘记了使用设计模式或者某种特定技术的理由,这时就值得我们返回来思考为什么要使用它。每项技术或者每个技术决策都有它的优势和不足,如果不了解其缺点,你需要知道你失去了什么。
数据库连接池生命周期
数据库每个读写操作需要一个连接。数据库连接调用流如下图:
调用流程为:
- 应用数据层向DataSource请求数据库连接
- DataSource使用数据库Driver打开数据库连接
- 创建数据库连接,打开TCP socket
- 应用读/写数据库
- 如果该连接不再需要就关闭连接
- 关闭socket
容易推断出打开/关闭数据库连接是开销很大的操作。PostgreSQL为每个客户端连接产生一个分离的OS进程,因此高频率地打开/关闭数据库连接会使数据库管理系统压力增大。
重用数据库连接最明显的原因是:
- 减少应用程序和数据库管理系统创建/销毁TCP连接的OS I/O开销
- 减少JVM对象垃圾
使用连接池 VS 不使用连接池
我们来比较一下不使用连接池方法与使用HikariCP,HikariCP可能是目前最快的连接池框架。
该测试将打开和关闭1000个连接。
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceConnectionTest.class); private static final int MAX_ITERATIONS = 1000; private Slf4jReporter logReporter; private Timer timer; protected abstract DataSource getDataSource(); @Before public void init() { MetricRegistry metricRegistry = new MetricRegistry(); this.logReporter = Slf4jReporter .forRegistry(metricRegistry) .outputTo(LOGGER) .build(); timer = metricRegistry.timer("connection"); } @Test public void testOpenCloseConnections() throws SQLException { for (int i = 0; i < MAX_ITERATIONS; i++) { Timer.Context context = timer.time(); getDataSource().getConnection().close(); context.stop(); } logReporter.report(); }
下面的图表为打开和关闭连接花费的时间,这个时间当然越短越好。
使用连接池比不使用连接池快600倍。我们的企业系统包括几十个应用,一个批处理器系统仅仅能够处理每小时大于200万次数据库连接,所以2个数量级的优化是值得考虑的。
Type | No Pooling Time (milliseconds) | Connection Pooling Time (milliseconds) |
---|---|---|
min | 74.551414 | 0.002633 |
max | 146.69324 | 125.528047 |
mean | 78.216549 | 0.128900 |
stddev | 5.9438335 | 3.969438 |
median | 76.150440 | 0.003218 |
为什么连接池快很多?
理解使用数据库连接池后运行如此好的原因,要分析池连接管理的调用流程:
无论何时请求一个连接,池数据源会从可用的连接池获取新连接。仅当没有可用的连接而且未达到最大的连接数时连接池将创建新的连接。连接池的close()方法把连接返回到连接池而不是真正地关闭它。
更快更安全
连接池是即将到来的连接请求的有界缓冲区。如果出现瞬间流量尖峰,连接池会平缓这一变化,而不是使所有可用数据库资源趋于饱和。
等待步骤和超时机制是安全钩子(safety hook),防止数据库服务器过载。如果一个应用消耗太多数据库流量,为防止它将数据库服务器压垮(因此影响整个系统),连接池将减少它对数据库的使用。
更大的能力带来更多的职责
所有这些优势都是有代价的,连接池配置的额外复杂性增加(尤其是大型企业级系统中)。所以没有银弹,你需要注意很多连接池配置比如:
- 最小连接数
- 最大连接数
- 最大空闲时间
- 获取连接超时时间
- 超时重试连接次数
下一篇文章将研究企业级数据库连接池的挑战和Flexy Pool如何帮助你找到合适的数据库连接池大小。
- 从GitHub获取代码
原文链接: javacodegeeks 翻译: ImportNew.com - hejiani
译文链接: http://www.importnew.com/11469.html
[ 转载请保留原文出处、译者和译文链接。]