現在的位置: 首頁 > 數據庫 > 正文

數據庫連接池的大小設置成多大合適

2020年01月16日 數據庫 ⁄ 共 3268字 ⁄ 字號 評論關閉

  一、數據庫連接池的大小

  基本上來說,大部分項目都需要跟數據庫做交互,那么,數據庫連接池的大小設置成多大合適呢?

  一些開發老鳥可能還會告訴你:沒關系,盡量設置的大些,比如設置成 200,這樣數據庫性能會高些,吞吐量也會大些!

  你也許會點頭稱是,真的是這樣嗎?看完這篇文章,也許會顛覆你的認知哦!

  二、正菜開始

  可以很直接的說,關于數據庫連接池大小的設置,每個開發者都可能在一環節掉進坑里,事實上呢,大部分程序員可能都會依靠自己的直覺去設置它的大小,設置成 100 ?思量許久后,自顧自想,應該差不多吧?

  三、假設你的服務有1萬并發的訪問

  不妨意淫一下,你手里有個網站,并發壓力雖然還沒到 Facebook 那個級別,但是呢?也有個1萬上下的并發量!也就是說差不多2萬左右的 TPS。

  那么問題來了!這個網站的數據庫連接池應該設置成多大合適呢?

  其實這個問法本身就是有問題的,我們需要反過來問,正確問法應該是:

  “這個網站的數據庫連接池應該設置成多小合適呢?”

  口述一下,視頻中對 Oracle 數據庫進行了壓力測試,模擬 9600 個并發線程來操作數據庫,每兩次數據庫操作之間 sleep 550ms,注意,視頻中剛開始設置的線程池大小為 2048。

  讓我們來看看數據庫連接池的大小為 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 核心的數量,再增加線程數系統就只會更慢,而不是更快,因為這里涉及到上下文切換耗費的額外的性能。

  說到這里,你應該恍然大悟了

  五、其他應該考慮到的因素

  上小節中說到了主要原因,但其實沒有這么簡單,我們還需要考慮到一些其他的因素。

  當我們在尋找數據庫的性能瓶頸時,大致可歸為三類:

  CPU

  磁盤 IO

  網絡 IO

  也許你會說,還有內存這一因素?內存的確是需要考慮的,但是比起磁盤IO和網絡IO,稍顯微不足道,這里就不加了。

  假設我們不考慮磁盤 IO 和網絡 IO,就很好定論了,在一個 8 核的服務器上,數據庫連接數/線程數設置為 8 能夠提供最優的性能,如果再增加連接數,反而會因為上下文切換導致性能下降。

  大家都知道,數據庫通常把數據存儲在磁盤上,而磁盤呢,通常是由一些旋轉著的金屬碟片和一個裝在步進馬達上的讀寫頭組成的。讀/寫頭同一時刻只能出現在一個位置,當它需要再次執行讀寫操作時,它必須“尋址”到另外一個位置才能完成任務。所以呢?這里就有了尋址的耗時,此外還有旋轉耗時,讀寫頭需要等待磁盤碟片上的目標數據“旋轉到位”才能進行讀寫操作。使用緩存當然是能夠提升性能的,但上述原理仍然適用。

  在這段("I/O等待")時間內,線程是處于“阻塞”等待狀態,也就是說沒干啥正事!此時操作系統可以將這個空閑的CPU 核心用于服務其他線程。

  這里我們可以總結一下,當你的線程處理的是 I/O 密集型業務時,便可以讓線程/連接數設置的比 CPU核心大一些,這樣就能夠在同樣的時間內,完成更多的工作,提升吞吐量。

  那么問題又來了?

  大小設置成多少合適呢?

  這要取決于磁盤,如果你使用的是 SSD 固態硬盤,它不需要尋址,也不需要旋轉碟片。打住打住!!!你千萬可別理所當然的認為:“既然SSD速度更快,我們把線程數的大小設置的大些吧!!”

  結論正好相反!無需尋址和沒有旋回耗時的確意味著更少的阻塞,所以更少的線程(更接近于CPU核心數)會發揮出更高的性能。只有當阻塞密集時,更多的線程數才能發揮出更好的性能。

  上面我們已經說過了磁盤 IO, 接下來我們談談網絡 IO!

  網絡 IO 其實也是非常相似的。通過以太網接口讀寫數據時也會造成阻塞,10G帶寬會比1G帶寬的阻塞耗時少一些,而 1G 帶寬又會比 100M 帶寬的阻塞少一些。通常情況下,我們把網絡 IO 放在第三順位來考慮,然而有些人會在性能計算中忽略網絡 IO 帶來的影響。

  上圖是 PostgreSQL 的基準性能測試數據,從圖中我們可以看到,TPS 在連接數達到 50 時開始變緩。回過頭來想下,在上面 Oracle 的性能測試視頻中,測試人員們將連接數從 2048 降到了 96,實際上 96 還是太高了,除非你的服務器 CPU 核心數有 16 或 32。

  六、連接數計算公式

  下面公式由 PostgreSQL 提供,不過底層原理是不變的,它適用于市面上絕大部分數據庫產品。還有,你應該模擬預期的訪問量,并通過下面的公式先設置一個偏合理的值,然后在實際的測試中,通過微調,來尋找最合適的連接數大小。

  連接數 = ((核心數 * 2) + 有效磁盤數)

  核心數不應包含超線程(hyper thread),即使打開了超線程也是如此,如果熱點數據全被緩存了,那么有效磁盤數實際是0,隨著緩存命中率的下降,有效磁盤數也逐漸趨近于實際的磁盤數。另外需要注意,這一公式作用于SSD 的效果如何,尚未明了。

  好了,按照這個公式,如果說你的服務器 CPU 是 4核 i7 的,連接池大小應該為 ((4 * 2) + 1) = 9。

  取個整, 我們就設置為 10 吧。你這個行不行啊?10 也太小了吧!

  你要是覺得不太行的話,可以跑個性能測試看看,我們可以保證,它能輕松支撐 3000 用戶以 6000 TPS 的速率并發執行簡單查詢的場景。你還可以將連接池大小超過 10,那時,你會看到響應時長開始增加,TPS 開始下降。

  七、結論:你需要的是一個小連接池,和一個等待連接的線程隊列

  假設說你有 10000 個并發訪問,而你設置了連接池大小為 10000,你怕是石樂志哦。

  改成 1000,太高?改成 100?還是太多了。

  你僅僅需要一個大小為 10 數據庫連接池,然后讓剩下的業務線程都在隊列里等待就可以了。

  連接池中的連接數量大小應該設置成:數據庫能夠有效同時進行的查詢任務數(通常情況下來說不會高于 2*CPU核心數)。

  你應該經常會看到一些用戶量不是很大的 web 應用中,為應付大約十來個的并發,卻將數據庫連接池設置成 100, 200 的情況。請不要過度配置您的數據庫連接池的大小。

  八、額外需要注意的點

  實際上,連接池的大小的設置還是要結合實際的業務場景來說事。

  比如說,你的系統同時混合了長事務和短事務,這時,根據上面的公式來計算就很難辦了。正確的做法應該是創建兩個連接池,一個服務于長事務,一個服務于"實時"查詢,也就是短事務。

  還有一種情況,比方說一個系統執行一個任務隊列,業務上要求同一時間內只允許執行一定數量的任務,這時,我們就應該讓并發任務數去適配連接池連接數,而不是連接數大小去適配并發任務數。

抱歉!評論已關閉.

奔驰宝马破解版下载 如何在网上开店赚钱 四肖免费提前公开h 深圳十大配资公司 好运南京麻将app下载 幸运赛车技巧全攻略 英超超级联赛 4人麻将在线玩 批量手机挂机项目 股票涨停又跌下来 富贵论坛手机版 fg美人捕鱼技巧秘籍 什么是权重股 网上正版棋牌 街机金蟾捕鱼旧版下载 股票涨停可以卖出吗 pk10公式