解惑:為什么300的並發能把支持最大連接數4000數據庫壓死?


問: 為什么300的並發能把支持最大連接數4000數據庫壓死?

 

  買了一台數據庫,最大連接數的參數是 4000,看起來很棒!但是 cpu 和內存並不咋好!是 2c4g的超低配制。

  但是想着反正業務量也不大,不如先扛着,等業務量上來再進行升配!

 

  沒過多久,進行一次小量的營銷活動。粗略計算想了下,大約3-4台應用服務器就沒問題了;然后再考慮下數據庫,應該沒有問題。

 

考慮到數據庫沒問題的原因有二:

  1. 應用服務器數量少,對數據庫壓力不會太大;

  2. 每個應用都設置了最大連接池限制,單台一般不會超過100的連接,與4000的並發連接指標還差很遠;

 

活動開始后,開始一切都很正常,應用服務器監控正常,前端響應正常。以為一切盡在掌握之中,結果卻是一場災難!

 

  前端頁面響應越來越慢了,監控應用服務器卻一點壓力沒上來!我知道是數據庫出問題了!

 

  於是,直接開了個db客戶端查看情況,自己試着運行了直sql,響應的確很慢,但是也能幾十秒內返回;所以我數粗淺的結論是,應用響應會很慢,但是應該能響應完整!

 

  其實,我想錯了。

  其一,前端訪問是有超時限制的,超過一段時間后,會自行斷開連接,所以后端超級卡頓時,前端用戶側是會無法提供服務的!

  其二,除去前端會有超時限制斷開外,應用api也會在一段時間沒有收到數據庫響應后,超時斷開返回,然而數據庫對斷開請求則可能收不到,從而繼續保持操作運行;從而應用服務器會再次發起下一個請求,從而使連接超過應用設置的連接池大小,進一步挑戰db極限;所以,前端仍然是不能正常服務的。

 

回到前面數據庫問題,為什么在還遠低於最大連接數的情況下,db就開始不工作了呢?

 

其實,db的運行指標,不止有最大連接數一個!cpu,內存,磁盤,網絡 都是其運行指標,這些指標都會限制其能力!

 

第一層,磁盤io。

  指標專業名詞:IOPS;因為所有的數據都是存儲在磁盤的,所以,在高並發的場景下,一定會受到磁盤能力的限制,普通磁盤 sata 可能只有7-10M/s 的能力,只要要求加載的數據遠遠大於這個速度,磁盤瓶頸就出來了。當然了,磁盤讀取后,結果是會緩存到內存的,所以又和內存有關了!

 

第二層,內存。

  磁盤讀取出來的數據必定會放到內存進行數據運算處理,然后才能得到結果。內存的速度當然是特別快了,咱們不考慮它這方面的能力問題。但是,速度再快,沒有內存空間就沒辦法了,就像上面的配置 4g 的內存其實稍微幾個大點的數據查詢,基本就裝滿了。而且,在一次查詢完成后,還要負責將結果緩存起來。當內存運行不夠的時候,cpu會進行磁盤的swap操作,將需要運算的數據換入內存,從而保證運算正常進行,但是這個操作就很慢了,從而導致正常的查詢都變得緩慢起來。(索引會稍微好點,因其數據量比較小,內存swap概率也低)。 所以,低配內存將是一大致命弱點,不要期望太高;

 

第三層,cpu。

  其實整個過程的調度都是由cpu來運籌帷幄的。只是,cpu運算速度往往都會很快,所以我們把它稍微放后點!因為前面磁盤和內存,導致cpu會不停地運算操作。另外,由於外部請求大量涌入,導致cpu要進行多線程的維護,即會有大量上下文切換,這個切換增加了cpu壓力,同時也使請求的響應變差,cpu也就越來越高,直到彪升到90+%,連操作系統的調度都很困難了。所以,只會雪上加霜地,降低請求的處理能力,從而導致db直接假死!可能只有重啟才能解決問題了!

 

第四層,網絡層。

  一般來說,只要數據庫和應用是部署在一個內網里,那么,網絡一般不會限制能力(非絕對);但是對於一些遠程數據庫,就直接要小心了,比如一個數據包就是3M+,那么如果是 10Mb/s 的帶寬,僅能傳輸3-4個數據包,從而使響應能力完全限死;所以,數據庫一般需要部署內網機房,或者買雲數據庫時,最好在同一區。網絡層一般我們可以忽略,但是要知道這里的原理!

 

最后,我們來討論下,mysql中的最大連接數到底是什么?

1. 查看最大連接數

    show variables like '%max_connections%'

2. 修改最大連接數

    set GLOBAL max_connections = 200;

那么,最大連接是什么原理呢?

  一般對於處理快速的情況下,每個連接進來后,會從mysql的線程池中取出線程來處理任務。但是當線程不夠用的時候,它會創建新的線程池來處理。

  所以,並發連接數越大,則往往意味着mysql的線程會越多(不一定是一對一);線程越多意味着上下文切換將越頻繁,cpu壓力越大,服務器性能越差。所以,合理設置最大連接數,使服務器處於高效狀態,是一個優化方向!

查看線程相關的狀態變量:

      SHOW STATUS LIKE 'Threads%';

 

那么問題來了,為什么阿里雲上的rds設置了這么高的最大連接數呢?我估計,他是為了兼容最快速和最小數據量的並發連接情況,而設置的。自己可以壓測下!

 

綜上,四個指標。只要有一個成為瓶頸,其他指標也就失去了意義!

 

其實真正有過mysql調優經驗的同學,深入理解過mysql,上面這些問題自然明白。而不明白的同學,則要多多實踐才行!

 

一句話總結:紙上得來終覺淺,絕知此事要躬行!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM