如何正確設(shè)置數(shù)據(jù)庫(kù)連接池的大兴藿浮?我的天蔬芥,原來(lái)之前都設(shè)置錯(cuò)了梆靖!

文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

歡迎關(guān)注個(gè)人微信公眾號(hào): 小哈學(xué)Java, 文末分享阿里 P8 資深架構(gòu)師吐血總結(jié)的 《Java 核心知識(shí)整理&面試.pdf》資源鏈接!笔诵!

個(gè)人網(wǎng)站: https://www.exception.site/essay/how-to-set-the-size-of-database-connection-pool

如何正確設(shè)置數(shù)據(jù)庫(kù)連接池大小

目錄

  • 一返吻、筆者前言
  • 二、正菜開始
  • 三乎婿、假設(shè)你的服務(wù)有1萬(wàn)并發(fā)的訪問(wèn)
  • 四测僵、為啥有這種效果?
  • 五、其他應(yīng)該考慮到的因素
  • 六、連接數(shù)計(jì)算公式
  • 七捍靠、結(jié)論:你需要的是一個(gè)小連接池沐旨,和一個(gè)等待連接的線程隊(duì)列
  • 八、額外需要注意的點(diǎn)

一榨婆、筆者前言

基本上來(lái)說(shuō)磁携,大部分項(xiàng)目都需要跟數(shù)據(jù)庫(kù)做交互,那么良风,數(shù)據(jù)庫(kù)連接池的大小設(shè)置成多大合適呢谊迄?

一些開發(fā)老鳥可能還會(huì)告訴你:沒關(guān)系,盡量設(shè)置的大些烟央,比如設(shè)置成 200统诺,這樣數(shù)據(jù)庫(kù)性能會(huì)高些,吞吐量也會(huì)大些疑俭!

你也許會(huì)點(diǎn)頭稱是粮呢,真的是這樣嗎?看完這篇文章怠硼,也許會(huì)顛覆你的認(rèn)知哦鬼贱!

你不要騙我

二、正菜開始

可以很直接的說(shuō)香璃,關(guān)于數(shù)據(jù)庫(kù)連接池大小的設(shè)置这难,每個(gè)開發(fā)者都可能在一環(huán)節(jié)掉進(jìn)坑里,事實(shí)上呢葡秒,大部分程序員可能都會(huì)依靠自己的直覺去設(shè)置它的大小姻乓,設(shè)置成 100 ?思量許久后眯牧,自顧自想蹋岩,應(yīng)該差不多吧?

三学少、假設(shè)你的服務(wù)有1萬(wàn)并發(fā)的訪問(wèn)

不妨意淫一下剪个,你手里有個(gè)網(wǎng)站,并發(fā)壓力雖然還沒到 Facebook 那個(gè)級(jí)別版确,但是呢扣囊?也有個(gè)1萬(wàn)上下的并發(fā)量!也就是說(shuō)差不多2萬(wàn)左右的 TPS绒疗。

那么問(wèn)題來(lái)了侵歇!這個(gè)網(wǎng)站的數(shù)據(jù)庫(kù)連接池應(yīng)該設(shè)置成多大合適呢?

其實(shí)這個(gè)問(wèn)法本身就是有問(wèn)題的吓蘑,我們需要反過(guò)來(lái)問(wèn)惕虑,正確問(wèn)法應(yīng)該是:

“這個(gè)網(wǎng)站的數(shù)據(jù)庫(kù)連接池應(yīng)該設(shè)置成多小合適呢?”

PS: 這里有一個(gè) Oracle 性能小組發(fā)布的簡(jiǎn)短視頻,鏈接地址為 http://www.dailymotion.com/video/x2s8uec

oracle性能測(cè)試視頻

口述一下溃蔫,視頻中對(duì) Oracle 數(shù)據(jù)庫(kù)進(jìn)行了壓力測(cè)試健提,模擬 9600 個(gè)并發(fā)線程來(lái)操作數(shù)據(jù)庫(kù),每?jī)纱螖?shù)據(jù)庫(kù)操作之間 sleep 550ms酒唉,注意矩桂,視頻中剛開始設(shè)置的線程池大小為 2048。

讓我們來(lái)看看數(shù)據(jù)庫(kù)連接池的大小為 2048 性能測(cè)試結(jié)果的鬼樣子:

每個(gè)請(qǐng)求要在連接池隊(duì)列里等待 33ms痪伦,獲得連接之后侄榴,執(zhí)行SQL需要耗時(shí)77ms, CPU 消耗維持在 95% 左右;

接下來(lái)网沾,我們將連接池的大小改小點(diǎn)癞蚕,設(shè)置成 1024,其他測(cè)試參數(shù)不變辉哥,結(jié)果咋樣桦山?

"這里,獲取連接等待時(shí)長(zhǎng)基本不變醋旦,但是 SQL 的執(zhí)行耗時(shí)降低了恒水!"

哎呦,有長(zhǎng)進(jìn)哦饲齐!

接下來(lái)钉凌,我們?cè)僭O(shè)置小些,連接池的大小降低到 96捂人,并發(fā)數(shù)等其他參數(shù)不變御雕,看看結(jié)果如何:

每個(gè)請(qǐng)求在連接池隊(duì)列中的平均等待時(shí)間為 1ms, SQL 執(zhí)行耗時(shí)為 2ms.

我去!什么鬼滥搭?

我們沒調(diào)整任何東西酸纲,僅僅只是將數(shù)據(jù)庫(kù)連接池的大小降低了,這樣瑟匆,就能把之前平均 100ms 響應(yīng)時(shí)間縮短到了 3ms闽坡。吞吐量指數(shù)級(jí)上升啊愁溜!

你這也太溜了无午!

吃驚

四、為啥有這種效果?

我們不妨想一下祝谚,為啥 Nginx 內(nèi)部?jī)H僅使用了 4 個(gè)線程,其性能就大大超越了 100 個(gè)進(jìn)程的 Apache HTTPD 呢酣衷?追究其原因的話交惯,回想一下計(jì)算機(jī)科學(xué)的基礎(chǔ)知識(shí),答案其實(shí)非常明顯。

要知道席爽,即使是單核 CPU 的計(jì)算機(jī)也能“同時(shí)”運(yùn)行著數(shù)百個(gè)線程意荤。但我們其實(shí)都知道,這只不過(guò)是操作系統(tǒng)快速切換時(shí)間片只锻,跟我們玩的一個(gè)小把戲罷了玖像。

一核 CPU同一時(shí)刻只能執(zhí)行一個(gè)線程,然后操作系統(tǒng)切換上下文齐饮,CPU 核心快速調(diào)度捐寥,執(zhí)行另一個(gè)線程的代碼,不停反復(fù)祖驱,給我們?cè)斐闪怂羞M(jìn)程同時(shí)運(yùn)行假象握恳。

其實(shí),在一核 CPU 的機(jī)器上捺僻,順序執(zhí)行AB永遠(yuǎn)比通過(guò)時(shí)間分片切換“同時(shí)”執(zhí)行AB要快乡洼,其中原因,學(xué)過(guò)操作系統(tǒng)這門課程的童鞋應(yīng)該很清楚匕坯。一旦線程的數(shù)量超過(guò)了 CPU 核心的數(shù)量束昵,再增加線程數(shù)系統(tǒng)就只會(huì)更慢,而不是更快葛峻,因?yàn)檫@里涉及到上下文切換耗費(fèi)的額外的性能锹雏。

說(shuō)到這里,你應(yīng)該恍然大悟了 ……

我懂了

五泞歉、其他應(yīng)該考慮到的因素

上小節(jié)中說(shuō)到了主要原因逼侦,但其實(shí)沒有這么簡(jiǎn)單,我們還需要考慮到一些其他的因素腰耙。

當(dāng)我們?cè)趯ふ覕?shù)據(jù)庫(kù)的性能瓶頸時(shí)榛丢,大致可歸為三類:

  • CPU
  • 磁盤 IO
  • 網(wǎng)絡(luò) IO

也許你會(huì)說(shuō),還有內(nèi)存這一因素挺庞??jī)?nèi)存的確是需要考慮的晰赞,但是比起磁盤IO網(wǎng)絡(luò)IO,稍顯微不足道选侨,這里就不加了掖鱼。

假設(shè)我們不考慮磁盤 IO 和網(wǎng)絡(luò) IO,就很好定論了援制,在一個(gè) 8 核的服務(wù)器上戏挡,數(shù)據(jù)庫(kù)連接數(shù)/線程數(shù)設(shè)置為 8 能夠提供最優(yōu)的性能,如果再增加連接數(shù)晨仑,反而會(huì)因?yàn)樯舷挛那袚Q導(dǎo)致性能下降褐墅。

大家都知道拆檬,數(shù)據(jù)庫(kù)通常把數(shù)據(jù)存儲(chǔ)在磁盤上,而磁盤呢妥凳,通常是由一些旋轉(zhuǎn)著的金屬碟片和一個(gè)裝在步進(jìn)馬達(dá)上的讀寫頭組成的竟贯。讀/寫頭同一時(shí)刻只能出現(xiàn)在一個(gè)位置,當(dāng)它需要再次執(zhí)行讀寫操作時(shí)逝钥,它必須“尋址”到另外一個(gè)位置才能完成任務(wù)屑那。所以呢?這里就有了尋址的耗時(shí)艘款,此外還有旋轉(zhuǎn)耗時(shí)持际,讀寫頭需要等待磁盤碟片上的目標(biāo)數(shù)據(jù)“旋轉(zhuǎn)到位”才能進(jìn)行讀寫操作。使用緩存當(dāng)然是能夠提升性能的磷箕,但上述原理仍然適用选酗。

在這段("I/O等待")時(shí)間內(nèi),線程是處于“阻塞”等待狀態(tài)岳枷,也就是說(shuō)沒干啥正事芒填!此時(shí)操作系統(tǒng)可以將這個(gè)空閑的CPU 核心用于服務(wù)其他線程。

這里我們可以總結(jié)一下空繁,當(dāng)你的線程處理的是 I/O 密集型業(yè)務(wù)時(shí)殿衰,便可以讓線程/連接數(shù)設(shè)置的比 CPU核心大一些,這樣就能夠在同樣的時(shí)間內(nèi)盛泡,完成更多的工作闷祥,提升吞吐量。

那么問(wèn)題又來(lái)了傲诵?

大小設(shè)置成多少合適呢凯砍?

這要取決于磁盤,如果你使用的是 SSD 固態(tài)硬盤拴竹,它不需要尋址悟衩,也不需要旋轉(zhuǎn)碟片。打住打姿ò荨W尽!幕与!你千萬(wàn)可別理所當(dāng)然的認(rèn)為:“既然SSD速度更快挑势,我們把線程數(shù)的大小設(shè)置的大些吧!啦鸣!

結(jié)論正好相反潮饱!無(wú)需尋址和沒有旋回耗時(shí)的確意味著更少的阻塞,所以更少的線程(更接近于CPU核心數(shù))會(huì)發(fā)揮出更高的性能诫给。只有當(dāng)阻塞密集時(shí)香拉,更多的線程數(shù)才能發(fā)揮出更好的性能饲漾。

上面我們已經(jīng)說(shuō)過(guò)了磁盤 IO, 接下來(lái)我們談?wù)劸W(wǎng)絡(luò) IO!

網(wǎng)絡(luò) IO 其實(shí)也是非常相似的缕溉。通過(guò)以太網(wǎng)接口讀寫數(shù)據(jù)時(shí)也會(huì)造成阻塞,10G帶寬會(huì)比1G帶寬的阻塞耗時(shí)少一些吃型,而 1G 帶寬又會(huì)比 100M 帶寬的阻塞少一些证鸥。通常情況下,我們把網(wǎng)絡(luò) IO 放在第三順位來(lái)考慮勤晚,然而有些人會(huì)在性能計(jì)算中忽略網(wǎng)絡(luò) IO 帶來(lái)的影響枉层。

PostgreSQL的benchmark數(shù)據(jù)

上圖是 PostgreSQL 的基準(zhǔn)性能測(cè)試數(shù)據(jù),從圖中我們可以看到赐写,TPS 在連接數(shù)達(dá)到 50 時(shí)開始變緩鸟蜡。回過(guò)頭來(lái)想下挺邀,在上面 Oracle 的性能測(cè)試視頻中揉忘,測(cè)試人員們將連接數(shù)從 2048 降到了 96,實(shí)際上 96 還是太高了端铛,除非你的服務(wù)器 CPU 核心數(shù)有 16 或 32泣矛。

六、連接數(shù)計(jì)算公式

下面公式由 PostgreSQL 提供禾蚕,不過(guò)底層原理是不變的您朽,它適用于市面上絕大部分?jǐn)?shù)據(jù)庫(kù)產(chǎn)品。還有换淆,你應(yīng)該模擬預(yù)期的訪問(wèn)量哗总,并通過(guò)下面的公式先設(shè)置一個(gè)偏合理的值,然后在實(shí)際的測(cè)試中倍试,通過(guò)微調(diào)讯屈,來(lái)尋找最合適的連接數(shù)大小。

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

核心數(shù)不應(yīng)包含超線程(hyper thread)易猫,即使打開了超線程也是如此耻煤,如果熱點(diǎn)數(shù)據(jù)全被緩存了,那么有效磁盤數(shù)實(shí)際是0准颓,隨著緩存命中率的下降哈蝇,有效磁盤數(shù)也逐漸趨近于實(shí)際的磁盤數(shù)。另外需要注意攘已,這一公式作用于SSD 的效果如何炮赦,尚未明了。

好了样勃,按照這個(gè)公式吠勘,如果說(shuō)你的服務(wù)器 CPU 是 4核 i7 的性芬,連接池大小應(yīng)該為 ((4 * 2) + 1) = 9

取個(gè)整, 我們就設(shè)置為 10 吧剧防。你這個(gè)行不行爸诧薄?10 也太小了吧峭拘!

行不行啊

你要是覺得不太行的話俊庇,可以跑個(gè)性能測(cè)試看看,我們可以保證鸡挠,它能輕松支撐 3000 用戶以 6000 TPS 的速率并發(fā)執(zhí)行簡(jiǎn)單查詢的場(chǎng)景辉饱。你還可以將連接池大小超過(guò) 10,那時(shí)拣展,你會(huì)看到響應(yīng)時(shí)長(zhǎng)開始增加彭沼,TPS 開始下降。

七备埃、結(jié)論:你需要的是一個(gè)小連接池姓惑,和一個(gè)等待連接的線程隊(duì)列

假設(shè)說(shuō)你有 10000 個(gè)并發(fā)訪問(wèn),而你設(shè)置了連接池大小為 10000瓜喇,你怕是石樂志哦挺益。

改成 1000,太高乘寒?改成 100望众?還是太多了。

你僅僅需要一個(gè)大小為 10 數(shù)據(jù)庫(kù)連接池伞辛,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了烂翰。

連接池中的連接數(shù)量大小應(yīng)該設(shè)置成:數(shù)據(jù)庫(kù)能夠有效同時(shí)進(jìn)行的查詢?nèi)蝿?wù)數(shù)(通常情況下來(lái)說(shuō)不會(huì)高于 2*CPU核心數(shù))。

你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的 web 應(yīng)用中蚤氏,為應(yīng)付大約十來(lái)個(gè)的并發(fā)甘耿,卻將數(shù)據(jù)庫(kù)連接池設(shè)置成 100, 200 的情況竿滨。請(qǐng)不要過(guò)度配置您的數(shù)據(jù)庫(kù)連接池的大小佳恬。

八、額外需要注意的點(diǎn)

實(shí)際上于游,連接池的大小的設(shè)置還是要結(jié)合實(shí)際的業(yè)務(wù)場(chǎng)景來(lái)說(shuō)事毁葱。

比如說(shuō),你的系統(tǒng)同時(shí)混合了長(zhǎng)事務(wù)短事務(wù)贰剥,這時(shí)倾剿,根據(jù)上面的公式來(lái)計(jì)算就很難辦了。正確的做法應(yīng)該是創(chuàng)建兩個(gè)連接池蚌成,一個(gè)服務(wù)于長(zhǎng)事務(wù)前痘,一個(gè)服務(wù)于"實(shí)時(shí)"查詢凛捏,也就是短事務(wù)。

還有一種情況芹缔,比方說(shuō)一個(gè)系統(tǒng)執(zhí)行一個(gè)任務(wù)隊(duì)列坯癣,業(yè)務(wù)上要求同一時(shí)間內(nèi)只允許執(zhí)行一定數(shù)量的任務(wù),這時(shí)最欠,我們就應(yīng)該讓并發(fā)任務(wù)數(shù)去適配連接池連接數(shù)坡锡,而不是連接數(shù)大小去適配并發(fā)任務(wù)數(shù)。

Ref

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

免費(fèi)分享 | 面試&學(xué)習(xí)福利資源

最近在網(wǎng)上發(fā)現(xiàn)一個(gè)不錯(cuò)的 PDF 資源《Java 核心知識(shí)&面試.pdf》分享給大家窒所,不光是面試,學(xué)習(xí)帆锋,你都值得擁有3橙 !锯厢!

獲取方式: 關(guān)注公眾號(hào): 小哈學(xué)Java, 后臺(tái)回復(fù)資源皮官,既可免費(fèi)無(wú)套路獲取資源鏈接,下面是目錄以及部分截圖:

關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】实辑,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】捺氢,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】剪撬,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】摄乒,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦

重要的事情說(shuō)兩遍残黑,關(guān)注公眾號(hào): 小哈學(xué)Java, 后臺(tái)回復(fù)資源馍佑,既可免費(fèi)無(wú)套路獲取資源鏈接 !@嫠拭荤!

歡迎關(guān)注微信公眾號(hào): 小哈學(xué)Java

關(guān)注微信公眾號(hào)【小哈學(xué)Java】,回復(fù)【資源】,即可免費(fèi)無(wú)套路領(lǐng)取資源鏈接哦
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疫诽,一起剝皮案震驚了整個(gè)濱河市舅世,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奇徒,老刑警劉巖雏亚,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異逼龟,居然都是意外死亡评凝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門腺律,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奕短,“玉大人宜肉,你說(shuō)我怎么就攤上這事◆岜” “怎么了谬返?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)日杈。 經(jīng)常有香客問(wèn)我遣铝,道長(zhǎng),這世上最難降的妖魔是什么莉擒? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任酿炸,我火速辦了婚禮,結(jié)果婚禮上涨冀,老公的妹妹穿的比我還像新娘填硕。我一直安慰自己,他們只是感情好鹿鳖,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布扁眯。 她就那樣靜靜地躺著,像睡著了一般翅帜。 火紅的嫁衣襯著肌膚如雪姻檀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天涝滴,我揣著相機(jī)與錄音绣版,去河邊找鬼。 笑死歼疮,一個(gè)胖子當(dāng)著我的面吹牛僵娃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腋妙,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼默怨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了骤素?” 一聲冷哼從身側(cè)響起匙睹,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎济竹,沒想到半個(gè)月后痕檬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡送浊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年梦谜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唁桩,死狀恐怖闭树,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荒澡,我是刑警寧澤报辱,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站单山,受9級(jí)特大地震影響碍现,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜米奸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一昼接、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悴晰,春花似錦辩棒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钻弄。三九已至佃却,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窘俺,已是汗流浹背饲帅。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘤泪,地道東北人灶泵。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像对途,于是被迫代替她去往敵國(guó)和親赦邻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容