【性能調優】數據庫連接池配置優化

在性能調優過程中,通過監控數據經常發現接口花費大量時間在獲取數據庫連接中,那如何通過優化數據庫連接池的配置來優化服務的性能呢?

什麼是數據庫連接池

創建數據庫連接是一個很耗時的操作,也容易對數據庫造成安全隱患。所以,在程序初始化的時候,集中創建多個數據庫連接,並把他們集中管理,供程序使用,可以保證較快的數據庫讀寫速度,還更加安全可靠

官方解釋:
數據庫連接池(Connection pooling)是程序啓動時建立足夠的數據庫連接,並將這些連接組成一個連接池,由程序動態地對池中的連接進行申請,使用,釋放。

爲什麼需要連接池

任何數據庫的訪問都需要首先建立數據庫連接。這是一個複雜、緩慢的處理。牽涉到通信建立(包括 TCP 的三次握手)、認證、授權、資源的初始化和分配等一系列任務
在應用啓動時預先建立一些數據庫連接,應用程序使用已有的連接可以極大提高響應速度。另外,Web 服務應用當客戶很多時,有很多線程,連接數目過多以及頻繁創建/刪除連接也會影響數據庫的性能

連接池帶來的好處:

  • 節省了創建數據庫連接的時間,通常這個時間大大超過處理數據訪問請求的時間
  • 統一管理數據庫請求連接,避免了過多連接或頻繁創建/刪除連接帶來的性能問題
  • 監控數據庫連接的運行狀態和錯誤報告,減少應用服務的這部分代碼

實現原理

在應用開始時創建一組數據庫的連接,也可以動態創建但是複用已有的連接。這些連接被存儲到一個共享的資源數據結構,稱爲連接池(典型的生產者-消費者併發模型)

連接邏輯
每個線程在需要訪問數據庫時借用(borrow)一個連接,使用完成則釋放(release)連接回到連接池供其他線程使用
比較好的線程池構件會有二個參數動態控制線程池的大小:最小數量和最大數量

最小數量指即使負載很輕,也保持一個最小數目的數據庫連接以備不時之需
當同時訪問數據庫的線程數超過最小數量時,則動態創建更多連接。最大數量則是允許的最大數據庫連接數量,當最大數目的連接都在使用而有新的線程需要訪問數據庫時,則新的線程會被阻塞直到有連接被釋放回連接池
當負載變低,池裏的連接數目超過最小數目而只有低於或等於最小數目的連接被使用時,超過最小數目的連接會被關閉和刪除以便節省系統資源。

連接泄露
連接池的實際應用中,最擔心的問題就是借了不還的這種讓其他人無資源可用的人品問題
編碼邏輯錯誤或者釋放連接放代碼沒有放到 finally 部分都會導致連接池資源枯竭從而造成系統變慢甚至完全阻塞的情況。類似於內存泄露,因而也叫連接泄露

連接池系統架構

連接池只是給業務應用提供已建立的連接,所有的訪問請求都通過連接轉發到後臺數據庫服務器
具體來說,連接池是兩個線程池的中間通道。可以看成下面的結構:
在這裏插入圖片描述
上圖中,連接池和應用服務線線程池在同一個進程裏面。每個訪問數據庫的應用服務進程都有自己的線程池和對應的數據庫連接池。數據庫服務器可能需要處理來自一個或多個服務器的多個應用服務進程內的數據庫連接池數據訪問請求

連接池的運行機制

  1. 程序初始化時創建連接池
  2. 使用時向連接池申請可用連接
  3. 使用完畢,將連接返還給連接池
  4. 程序退出時,斷開所有連接,並釋放資源

配置考慮因素

  • 當前連接DB的規模
  • 併發情況
  • 執行db的響應時間

做爲應用服務和數據庫的橋樑,連接池參數配置的目標是全局優化。具體的優化目的有四個:

  1. 儘可能滿足應用服務的併發數據庫訪問
  2. 不讓數據庫服務器過載
  3. 能發現用了不還造成的死鎖
  4. 不浪費系統資源

不浪費系統資源是指配置過大的連接池會浪費應用服務器的系統資源,包括內存,網絡端口,同步信號等。同時線程池的重啓和操作都會響應變慢。不過應用端連接池的開銷不是很大,資源的浪費通常不是太大問題

配置參數解讀

  1. 初始化連接:可考慮設置爲3個連接 。對於db規模特別大的情況下可考慮設置爲1個。避免啓動時間過長
  2. 最小連接:可考慮該值的設置和初始化連接保持一致
  3. 最大連接:對於有較大DB規模,最大連接不要設置過大,避免本地維護的db太大。如果對應到數據源的併發數過高,可考慮增大最大連接數
  4. 獲取連接的超時時間:如果連接全部被佔用,需要等待的時間。可以根據當前系統的響應時間判定,如果容忍度較高,可以大點。容忍度較低,設置小點
  5. 獲取連接和釋放連接心跳檢測:建議全部關閉,否則每個數據庫訪問指令會對數據庫生產額外的兩條心跳檢測的指令,增加數據庫的負載。連接有效性的檢查改用後臺空閒連接檢查
  6. 連接有效性檢測時間:該值需要結合數據庫的wait_timeout,interactive_timeout值進行設置。假如數據庫爲120s,則心跳檢測時間在120s以內越大越好。如果太小,心跳檢測時間會比較頻繁。建議設置爲90s
  7. 最大空閒時間:如果連接超過該時間沒有使用過,則會進行close掉。 該值不要太小,避免頻繁的建立連接關閉連接。也不要太大,導致一直無法關閉
  8. 心跳檢查的sql語句:儘量使用ping命令,ping的性能較查詢語句高。大部分的數據庫連接池不配置query語句,便會調用ping命令。
  9. prepareStatement緩存:可以根據自己的業務來判定是否開啓。開啓後對性能的影響依賴於具體業務和併發情況。可考慮暫時不開啓
  10. 連接使用超時:業務拿到一個連接,如果超過指定的時間未歸還,是否把該連接給給回收掉。超時時間等和具體的業務關聯。暫時建議先不開啓

如何配置數據庫連接池

druid配置
介紹:https://github.com/alibaba/druid
在這裏插入圖片描述
配置說明:

  1. minEvictableIdleTimeMillis(最大空閒時間):默認爲30分鐘,配置裏面不進行設置
  2. testOnBorrow ,testOnReturn 默認爲關閉,可以設置爲不配置
  3. testWhileIdle(在獲取連接後,確定是否要進行連接空閒時間的檢查)。默認爲true。配置裏面不再進行設置

流程說明:

  1. 在第一次調用connection的時候,纔會進行 initialSize的初始化
  2. 心跳檢測時間線程,會休眠timeBetweenEvictionRunsMillis時間,然後只對(沒有borrow的線程 減去 minIdle)的線程進行檢查,如果空閒時間大於minEvictableIdleTimeMillis則進行close
  3. testWhileIdle必須設置爲true,在獲取到連接後,先檢查testOnBorrow,然後再判定testwhileIdle,如果連接空閒時間大於timeBetweenEvictionRunsMillis,則會進行心跳檢測
  4. 不需要配置validationQuery,如果不配置的情況下會走ping命令,性能更高
  5. 連接保存在數組裏面,獲取連接的時候,獲取數組的最後一位。在timeBetweenEvictionRunsMillis時是從前往後進行檢查連接的有效性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章