資料庫連線池的大小

2021-09-24 21:22:57 字數 2154 閱讀 7279

基本上來說,大部分專案都需要跟資料庫做互動,那麼資料庫連線池的大小設定成多大合適呢?一些同學可能會很隨意的告訴你:沒關係,盡量設定的大些,比如設定成200, 這樣資料庫效能會高寫,吞吐量也會大些。真的是這樣嗎?

關於資料庫連線池大小的設定,每乙個開發都有可能在這一環節掉進坑里。事實上大部分程式設計師可能都會依靠自己的直覺去設定它的大小,設定成100?思量許久後,應該差不多吧?

案例

某個團隊對oracle資料庫進行了壓力測試,模擬9600個併發執行緒來運算元據庫,每兩次資料庫操作之間sleep 550ms,最開始的時候設定的執行緒池大小為2048。測試結果是:每個請求要在連線池佇列裡面等待33ms,獲得連線之後,執行sql需要耗時77ms,cpu消耗維持在95%左右。

接下來將連線池大小改小點,設定成1024, 其他測試引數不變,測試結果:獲取連線等待時長基本不變,但是sql的執行耗時降低了。

接下來再設定小一些,連線池大小降低到96, 併發數等其他引數不變,測試結果:每個請求再連線池佇列中的平均等待時間為1ms,sql執行耗時為2ms。

我們沒有調整任何東西,僅僅只是將資料庫連線池的大小降低了,這樣就能把之前平均100ms的相應時間縮短到了3ms,吞吐量指數級上公升。

為什麼會有這種效果?

我們不妨想一下,為啥nginx內部僅僅使用了4個執行緒,其效能就大大超越了100個執行緒的apache httpd?要知道,即使是單核cpu的計算機也能「同時」執行著數百個執行緒,但我們其實都知道,這只不過是作業系統快速切換時間片,跟我們玩的乙個小把戲罷了。

一核cpu同一時刻只能執行乙個執行緒,然後作業系統切換上下文,cpu核心快速調整,執行另外乙個執行緒的**,不停反覆,給我們造成了所有程序同時執行的假象。

其實,在一核cpu的機器上,順序執行a和b永遠比通過時間分片切換「同時」執行a和b要快,一旦執行緒的數量超過了cpu核心的數量,再增加執行緒數系統就只會更慢,而不是更快,因為這裡涉及到上下文切換耗費的額外的效能。

其他應該考慮到的因素

當我們再尋找資料庫的效能瓶頸時,大致可歸為三類:

a. cpu

b. 磁碟io

c. 網路io

也許你會說,還有記憶體,記憶體的確是需要考慮的,但是比起磁碟io和網路io,就稍顯微不足道了。

假設我們不考慮磁碟io和網路io,那就很好定論了,在乙個8核的伺服器上,資料庫連線數/執行緒數設定為8能夠提供最優的效能,如果再增加連線數,反而會因為上下文切換導致效能下降。

大家都知道,資料庫通常把資料儲存再磁碟上,而磁碟通常是由一些旋轉著的金屬碟片和乙個讀寫頭組成的。讀寫頭同一時刻只能出現在乙個位置,當它需要再次執行讀寫操作的時候,它必須「定址」到另外乙個位置才能完成任務。所以這裡就有了定址的耗時,此外還有旋轉耗時,讀寫頭需要等待磁碟碟片上的目標資料「旋轉到位」才能進行讀寫操作。在這段時間內,執行緒是出於「阻塞」等待狀態,也就是說沒乾啥正事,此時作業系統可以將這個空閒的cpu核心用於服務其他執行緒。

這裡我們可以總結一下,當你的執行緒處理的是i/o密集型業務時,便可以讓執行緒/連線數設定的比cpu核心數大一些,這樣就能夠在同樣的時間內,完成更多的工作,提公升吞吐量。

那麼設定成多少合適呢?這要取決於磁碟,如果你使用的是ssd固態硬碟,它不需要定址,也不需要旋轉碟片,意味著執行緒阻塞的時間很少,所以接近於cpu核心數的執行緒會發揮出更高的效能。只有當阻塞密集型時,更多的執行緒數才能發揮更好的效能。

上面我們了解了磁碟io,接下來我們談談網路io。網路io其實也非常的相似,通過乙太網介面讀取資料時也會造成阻塞,10g頻寬會比1g頻寬的阻塞耗時少一些,而1g頻寬又會比100m頻寬的阻塞少一些。通常情況下,我們把網路io放到第三順位來考慮。

連線數計算公式

下面公式由postgresql提供,它適用於市面上絕大部分資料庫產品。還有,你應該模擬預期的訪問量,並通過下面的公式先設定乙個偏合理的值,然後在實際的測試中,通過微調來尋找最合適的連線數大小。

連線數 = (核心數 * 2) + 有效磁碟數

按照這個公式,如果你的伺服器cpu是4核的,連線池大小應該為(4 * 2)+ 1 = 9,取個整我們就設定為10。如果你跑個效能測試就可以看到,它能輕鬆支撐3000使用者以6000tps的速率併發執行簡單查詢的場景。

資料庫連線池大小

一顆cpu核心同一時刻只能執行乙個執行緒,然後作業系統切換上下文,核心開始執行另乙個執行緒的 給定一顆cpu核心,其順序執行a和b永遠比通過時間分片 同時 執行a和b要快。一旦執行緒的數量超過了cpu核心的數量,再增加執行緒數系統只會更慢,而不是更快。連線數 核心數 2 有效磁碟數 公理 你需要乙個...

資料庫連線池 Redis連線池

基本原理 在內部物件池中,維護一定數量的資料庫連線,並對外暴露資料庫連線的獲取和返回方法。如外部使用者可通過getconnection方法獲取資料庫連線,使用完畢後再通過releaseconnection方法將連線返回,注意此時的連線並沒有關閉,而是由連線池管理器 並為下一次使用做好準備。2.作用 ...

資料庫連線池

實現資料連線池,讓系統有更高有執行效率 using system using system.data using system.data.sqlclient using system.collections using system.threading public class dataaccess...