資料庫連線池淺析

importnew發表於2014-05-21

 簡介

  我從事的所有專案都用到了資料庫連線池,這樣做自然有它的理由。有時我們可能忘記了使用設計模式或者某種特定技術的理由,這時就值得我們反思為什麼要使用它。每項技術或者每個技術決策都有它的優勢和不足,如果不瞭解其缺點,你需要知道你失去了什麼。

 資料庫連線池生命週期

  資料庫每個讀寫操作需要一個連線。資料庫連線呼叫流如下圖:

  呼叫流程為:

  1. 應用資料層向DataSource請求資料庫連線
  2. DataSource使用資料庫Driver開啟資料庫連線
  3. 建立資料庫連線,開啟TCP socket
  4. 應用讀/寫資料庫
  5. 如果該連線不再需要就關閉連線
  6. 關閉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 - hejiani

相關文章