天天看點

解惑:為什麼300的并發能把支援最大連接配接數4000資料庫壓死?

問: 為什麼300的并發能把支援最大連接配接數4000資料庫壓死?

買了一台資料庫,最大連接配接數的參數是 4000,看起來很棒!但是 cpu 和記憶體并不咋好!是 2c4g的超低配制。

 但是想着反正業務量也不大,不如先扛着,等業務量上來再進行升配!
           
沒過多久,進行一次小量的營銷活動。精力計算想了下,大量3-4台應用伺服器就沒問題了;然後再考慮下資料庫,應該沒有問題。
           

考慮到資料庫沒問題的原因有二:

1. 應用伺服器數量少,對資料庫壓力不會太大;

  2. 每個應用都設定了最大連接配接池限制,單台一般不會100的連接配接,與4000的并發連接配接名額還很遠;
           

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

前端頁面響應越來越慢了,監控應用伺服器卻一點壓力沒上來!我知道是資料庫出問題了!
           
于是,直接開了個db用戶端檢視情況,自己試着運作了直sql,響應的确很慢,但是也能幾十秒内傳回;是以我數粗淺的結論是,應用響應會很慢,但是應該能響應完整!
           
其實,我想錯了。前端通路是有逾時限制的,超過一段時間後,會自行斷開連接配接,是以後端超級卡頓時,前端使用者側是會無法提供服務的!

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

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

其實,db的運作名額,不止有最大連接配接數一個!cpu,記憶體,磁盤,網絡 都是其運作名額,這些名額都會限制其能力!

第一層,磁盤io。

因為所有的資料都是存儲在磁盤的,是以,在高并發的場景下,一定會受到磁盤能力的限制,普通磁盤 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,上面這些問題自然明白。而不明白的同學,則要多多實踐才行!

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

原文位址

https://www.cnblogs.com/yougewe/p/10576021.html