<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          這個關(guān)于連接池的結(jié)論,你絕對想不到

          共 3842字,需瀏覽 8分鐘

           ·

          2021-03-03 21:57


          Part1 前言


          在開源網(wǎng)站github上,有一段關(guān)于JDBC連接池的視頻,演示了同等業(yè)務(wù)壓力下,不同的連接池線程數(shù)設(shè)置對數(shù)據(jù)庫性能的影響,并用文字進(jìn)行了深入分析,得出在部分情況下,連接數(shù)/并發(fā)數(shù)并不一定是越高越好這樣有意思的結(jié)論,本文主要內(nèi)容為英文原文的翻譯(推薦閱讀原文,原文鏈接見文末)。


          連接池是創(chuàng)建和管理一個連接的緩沖池的技術(shù),這些連接準(zhǔn)備好被任何需要它們的線程使用。



          Part2 一個1萬用戶的測試



          發(fā)者在配置連接池的時候經(jīng)常會犯下一些錯誤,因為理解了一些連接池參數(shù)的意義之后,實際配置的數(shù)值可能是反直覺的。


          假設(shè)有一個網(wǎng)站總是有 10000 個用戶在訪問,并且 TPS 為 20000,一般都會這么考慮:連接池需要設(shè)置成多大才能承載這個業(yè)務(wù)壓力?但是真相可能會非常令人意外:需要考慮的是連接池需要設(shè)置成多小。


          第一輪測試使用了 2048 個線程作為連接池的配置,測試結(jié)果如下圖:


          2048線程


          TPS 約 160k 左右,實際 SQL 執(zhí)行的時間是 78ms,在連接池隊列的等待時間為 39ms,截圖最下方展示了等待事件的 TOP 5,數(shù)據(jù)庫層面有很多的等待事件。CPU 的使用率也很高(dbsvr1):


          CPU 使用率


          當(dāng)連接池的線程數(shù)降到 1024 的時候,測試結(jié)果如下圖:


          1024 線程


          TPS 約 170k 左右,沒有明顯的變化,隊列等待時間有少量下降,但是 SQL 的執(zhí)行時間從 78ms 降到了 38ms,效果很明顯。而等待事件中,CPU 等待事件也變多了。


          當(dāng)連接池的線程數(shù)降到 96 的時候,測試結(jié)果如下圖:


          96 線程


          TPS 約 200k 左右,提升了約 20%,隊列等待時間和 SQL 執(zhí)行時間都有大幅度的下降,等待事件中全部變成了 CPU 等待。



          Part3 原因是什么?



          不止數(shù)據(jù)庫,其他的軟件也有類似情況,比如 4 線程的 Nginx web-server 為什么會比 100 線程的 Apache web-server 性能要好。這實際上和計算機(jī) CPU 和系統(tǒng)的特點(diǎn)有關(guān),有時候,線程少比線程多要好。


          現(xiàn)實情況中,即便只有一核,看起來也能處理數(shù)十個或者是數(shù)百個線程。但是很多人(應(yīng)該要)知道這是是操作系統(tǒng)的時分(時間分片)技術(shù)帶來的效果。


          實際上一個核心是只能執(zhí)行一個線程的工作的,但是操作系統(tǒng)通過上下文切換讓 CPU 的核心把工作內(nèi)容切換成其他線程的任務(wù),通過不停的切換,達(dá)到了“并行處理工作”的效果。


          從理論上說,先執(zhí)行完工作 A,再執(zhí)行工作 B 是比通過上下文切換“并行”執(zhí)行要快,因為上下文切換是會浪費(fèi)時間的。因此一旦線程的數(shù)量超過了 CPU 的核心數(shù),繼續(xù)加線程數(shù)只會讓任務(wù)處理越來越慢。


          一、有限的資源


          當(dāng)然,實際情況并不會像上文描述一樣那么簡單,但是變慢的現(xiàn)象一般還是存在的。


          可能成為數(shù)據(jù)庫瓶頸的,一般就是三大基礎(chǔ)資源:CPU,磁盤,網(wǎng)絡(luò)。內(nèi)存其實也是應(yīng)該考慮的一項資源,不過內(nèi)存的帶寬和磁盤,網(wǎng)絡(luò)要差上幾個數(shù)量級,所以一般不會先遇到瓶頸。


          假設(shè)磁盤和網(wǎng)絡(luò)都沒有瓶頸,那么事情會變得很簡單:在一個 8 核的服務(wù)器上,8 個線程是最佳的性能,超過 8 線程之后就會因為上下文切換導(dǎo)致性能被浪費(fèi)。


          當(dāng)加上磁盤和網(wǎng)絡(luò)的影響之后,事情就不是那么簡單了,傳統(tǒng)的機(jī)械盤由于存在碟片轉(zhuǎn)動以及尋道時間等消耗,如果一個核心一直在處理一個線程的任務(wù),那么就會有不少時間處于“IO 等待”,觸發(fā)這個等待事件的時候 CPU 核心是空閑狀態(tài)的,因此通過上下文切換,去執(zhí)行其他線程的任務(wù)能夠高效的利用 CPU 核心的計算能力。


          因此在現(xiàn)實中,存在線程數(shù)高于 CPU 核心數(shù)時,性能在繼續(xù)提升的現(xiàn)象。


          那么到底線程數(shù)設(shè)置為多少會比較好?從上面的描述可以知道,這個數(shù)字取決于磁盤系統(tǒng),由于 SSD 存儲的普及,現(xiàn)在的磁盤存儲已經(jīng)沒有尋道時間或者碟片轉(zhuǎn)動的消耗了。那么因為 SSD 的“IO 等待”很少,所以能設(shè)置更高的線程數(shù)?


          結(jié)論可能是 180 度反轉(zhuǎn)的。正因為“IO 等待”很少,所以 CPU 在處理線程任務(wù)的時候,空閑(即被 IO 阻塞)的時間很少,所以線程數(shù)越接近核心數(shù),性能越好。更多的線程適合于經(jīng)常被阻塞的場景,因為大量的空閑、阻塞時間可以用來執(zhí)行其他線程的任務(wù)。


          網(wǎng)絡(luò)方面的情況也和磁盤比較類似,當(dāng)寫入的數(shù)據(jù)超過網(wǎng)卡的寫入/發(fā)送隊列的上限時,也會出現(xiàn)阻塞的情況,使用高流量,比如 10G 的網(wǎng)卡比 1G 的網(wǎng)卡更不容易出現(xiàn)阻塞。不過網(wǎng)絡(luò)瓶頸的優(yōu)先級較低,一般是最后才會考慮到的,甚至有一些人會完全忽略網(wǎng)絡(luò)瓶頸的可能性(取決于網(wǎng)絡(luò)環(huán)境建設(shè)能力)。


          圖表比文字更形象,可以參考如下測試結(jié)果圖:



          二、測試結(jié)果


          這個測試結(jié)果來自于 PostgreSQL 基準(zhǔn)測試,縱坐標(biāo)是 TPS,橫坐標(biāo)是 Client 數(shù)量,從 1 到 50 個線程的并發(fā),雖然測試中展示了線程數(shù)從 2048 降到 96 的測試結(jié)果,但是 96 實際上都太高了,除非服務(wù)器上的核心數(shù)有 16 個或者 32 個。


          三、計算公式


          PostgreSQL 項目組給了一個計算公式來計算并發(fā)的連接數(shù),計算出來的值可以作為最初的參考設(shè)置。這個計算方式其實對大多數(shù)數(shù)據(jù)庫都有參考價值。具體的設(shè)置建議以參考值為基準(zhǔn),盡量在接近生產(chǎn)壓力的環(huán)境下進(jìn)行測試和調(diào)整。


          計算公式為:connections = ((core_count * 2) + effective_spindle_count)


          core_count:不是“超線程”技術(shù)之后看到的核心數(shù),而是實際的核心數(shù)。


          effective_spindle_count:如果數(shù)據(jù)可以完全 cache 到內(nèi)存則取 0,否則隨著 cache 命中率降低,則這個數(shù)值會變高。MySQL 方面,可以認(rèn)為是 innodb_buffer_pool 的命中率。


          所以一個 4 核的酷睿 I7 服務(wù)器只有一塊磁盤的情況下,連接池的線程數(shù)可以設(shè)置成:9 = ((4 * 2) + 1),用 10 作為一個取整的數(shù)值就不錯。


          看起來有點(diǎn)低?可以試試看,可以打個賭,這個設(shè)置可以輕松支撐 3000 前端用戶,接近 6000 TPS 的簡單查詢。用同樣的硬件配置,當(dāng)連接數(shù)設(shè)置得比 10 高很多的時候,可以從壓力測試中看到 TPS 開始下降,前端用戶的響應(yīng)時間開始攀升。


          四、公理


          應(yīng)用需要一個小的“池子”,和等待使用這個池子中連接的應(yīng)用線程。


          如果有個網(wǎng)站有 10000 個前端用戶,連接池設(shè)置成 10000 會非常的瘋狂,1000 也會很恐怖,甚至 100 都過量了。


          實際上連接池的線程數(shù)只需要幾十就夠了,剩下的應(yīng)用線程只需要在連接池那里等待連接可用就行了。如果連接池的線程數(shù)參數(shù)已經(jīng)好好優(yōu)化過,那么這個設(shè)置一般不會比 core_count * 2 高,或者不會高很多。


          然而在實際情況中,內(nèi)部 web 應(yīng)用會使用一些“令人驚奇”的設(shè)置:比如,僅有幾十個用戶在周期性的執(zhí)行一些操作,但是連接池的線程數(shù)設(shè)置為 100。請不要過度配置這些參數(shù)和數(shù)據(jù)庫。


          五、Pool-locking


          Pool-locking 被關(guān)注的原因是會出現(xiàn)單個應(yīng)用層線程同時使用多個數(shù)據(jù)庫連接的情況,這個問題更多的是應(yīng)用層需要考慮的。


          當(dāng)然,增加連接池的線程數(shù)可以減少這種場景下互相搶占連接池線程的幾率,但是強(qiáng)烈建議先在應(yīng)用側(cè)考慮如果解決這個問題,而不是直接增大連接池的線程數(shù)。


          比如最大有 N 個應(yīng)用層的線程,每個應(yīng)用層的線程需要使用 M 個數(shù)據(jù)庫連接,那么連接池想要避免 Pool-locking 就至少需要N x (M - 1) +1個數(shù)據(jù)庫連接。在某些場景下,使用 JTA(Java Transaction Manager)可以顯著的減少當(dāng)個應(yīng)用層線程需要的數(shù)據(jù)庫連接數(shù),因為getConnection()這個函數(shù)會返回當(dāng)前事務(wù)已經(jīng)持有的數(shù)據(jù)庫連接。



          Part5 結(jié)論



          連接池的線程數(shù)和實際的情況是緊密相關(guān)的,連接數(shù)/并發(fā)數(shù)并不一定是越高越好。


          比如一套系統(tǒng)中,一部分業(yè)務(wù)邏輯使用長連接,一部分業(yè)務(wù)使用短連接,最好的辦法是創(chuàng)建兩個連接池,而不是考慮怎么去優(yōu)化一個池子的設(shè)置。


          另外一些系統(tǒng)則存在外部原因會限制數(shù)據(jù)庫連接數(shù),比如業(yè)務(wù)層的 JOB 并發(fā)數(shù)量是有上限的,或者是固定的,那么連接池的線程數(shù)就可以參考這些“外部原因”的限制,設(shè)置成一樣的值,或者是在這個數(shù)量附近浮動。


          聲明:本文由騰訊云數(shù)據(jù)庫產(chǎn)品團(tuán)隊整理翻譯,原內(nèi)容來自于github(原文鏈接:https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing),作者Leo Bayer@HikariCP。翻譯目的在于傳遞更多全球最新數(shù)據(jù)庫領(lǐng)域相關(guān)信息,侵權(quán)請聯(lián)系刪除。


          - End -


          《騰訊云數(shù)據(jù)庫專家服務(wù)》是由騰訊云數(shù)據(jù)庫技術(shù)服務(wù)團(tuán)隊維護(hù)的社區(qū)專欄,涵蓋了各類數(shù)據(jù)庫的實際案例,最佳實踐,版本特性等內(nèi)容。目前專欄文章仍在持續(xù)豐富中,歡迎在文章末尾留言互動,給出寶貴的建議。



          更多精彩


          用數(shù)據(jù)庫的三大糟心時刻,你中招了嗎


          98%的DBA不知道的數(shù)據(jù)庫內(nèi)存知識點(diǎn)


          ↓↓一年19.9特惠數(shù)據(jù)庫點(diǎn)這兒~ 

          瀏覽 81
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人黄色性生活视频 | 麻豆一区二区99久久久久 | 亚洲中文版字幕 | 欧美成人版H性爽997777 | 熊猫成人免费视频网站 |