数据库连接池浅析
簡介
我從事的所有項目都用到了數據庫連接池,這樣做自然有它的理由。有時我們可能忘記了使用設計模式或者某種特定技術的理由,這時就值得我們反思為什么要使用它。每項技術或者每個技術決策都有它的優勢和不足,如果不了解其缺點,你需要知道你失去了什么。
數據庫連接池生命周期
數據庫每個讀寫操作需要一個連接。數據庫連接調用流如下圖:
調用流程為:
容易推斷出打開/關閉數據庫連接是開銷很大的操作。PostgreSQL為每個客戶端連接產生一個分離的OS進程,因此高頻率地打開/關閉數據庫連接會使數據庫管理系統壓力增大。
重用數據庫連接最明顯的原因是:
- 減少應用程序和數據庫管理系統創建/銷毀TCP連接的OS I/O開銷
- 減少JVM對象垃圾
使用連接池 VS 不使用連接池
我們來比較一下不使用連接池方法與使用HikariCP,HikariCP可能是目前最快的連接池框架。
該測試將打開和關閉1000個連接。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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個數量級的優化是值得考慮的。
| 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獲取代碼
譯文鏈接:?http://www.importnew.com/11469.html
本文由?ImportNew?-?hejiani?翻譯自?javacodegeeks。
總結
- 上一篇: Java 多维数组遍历
- 下一篇: Java面试参考指南——同步