1. 程式人生 > >解惑:為什麽300的並發能把支持最大連接數4000數據庫壓死?

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

結果 難了 營銷 掌握 阿裏雲 並發連接 對數 應用服務 variable

問: 為什麽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,上面這些問題自然明白。而不明白的同學,則要多多實踐才行!

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

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