更新時間:2020-03-15 來源:黑馬程序員 瀏覽量:
一、什么是高并發(fā)
高并發(fā)(High Concurrency)是互聯(lián)網(wǎng)分布式系統(tǒng)架構(gòu)設(shè)計中必須考慮的因素之一,它通常是指,通過設(shè)計保證系統(tǒng)能夠同時并行處理很多請求。高并發(fā)相關(guān)常用的一些指標(biāo)有響應(yīng)時間(Response Time),吞吐量(Throughput),每秒查詢率QPS(Query Per Second),并發(fā)用戶數(shù)等。推薦了解黑馬程序員java培訓(xùn)課程。
響應(yīng)時間:系統(tǒng)對請求做出響應(yīng)的時間。例如系統(tǒng)處理一個HTTP請求需要200ms,這個200ms就是系統(tǒng)的響應(yīng)時間。
吞吐量:單位時間內(nèi)處理的請求數(shù)量。
QPS:每秒響應(yīng)請求數(shù)。在互聯(lián)網(wǎng)領(lǐng)域,這個指標(biāo)和吞吐量區(qū)分的沒有這么明顯。
并發(fā)用戶數(shù):同時承載正常使用系統(tǒng)功能的用戶數(shù)量。例如一個即時通訊系統(tǒng),同時在線量一定程度上代表了系統(tǒng)的并發(fā)用戶數(shù)。
二、什么是秒殺
秒殺場景一般會在電商網(wǎng)站舉行一些活動或者節(jié)假日在12306網(wǎng)站上搶票時遇到。對于電商網(wǎng)站中一些稀缺或者特價商品,電商網(wǎng)站一般會在約定時間點對其進行限量銷售,因為這些商品的特殊性,會吸引大量用戶前來搶購,并且會在約定的時間點同時在秒殺頁面進行搶購。
此種場景就是非常有特點的高并發(fā)場景,如果不對流量進行合理管控,肆意放任大流量沖擊系統(tǒng),那么將導(dǎo)致一系列的問題出現(xiàn),比如一些可用的連接資源被耗盡、分布式緩存的容量被撐爆、數(shù)據(jù)庫吞吐量降低,最終必然會導(dǎo)致系統(tǒng)產(chǎn)生雪崩效應(yīng)。
一般來說,大型互聯(lián)網(wǎng)站通常采用的做法是通過擴容、動靜分離、緩存、服務(wù)降級及限流五種常規(guī)手段來保護系統(tǒng)的穩(wěn)定運行。
三、如何解決秒殺的高并發(fā)
1. 限流
在討論為什么需要限流之前,我們先聊一聊生活中那些隨處可見的限流場景。
例如上下班高峰期,大量人群涌入地鐵站,會造成嚴重擁堵,原本從站廳到站臺最多只需花費5分鐘左右的時間,卻在被限流管制下被迫花費30分鐘或更久才能順利進入站臺。
上面兩張圖片就展示了地鐵擁擠的場景,如果這所有的人全部涌入站臺,那么會造成更多的人無法上車,所以采取了管制之后,我們可以讓人們通過地面和站廳層的雙重排隊等待,減輕站臺的壓力,保證每一位乘客最終都能順利的上車。
在電商系統(tǒng)的秒殺中,也會有大批量的用戶同時涌入,鑒于只有少部分用戶能夠秒殺成功,所以要限制大部分流量,只允許少部分流量進入服務(wù)后端。
限流可以采用限制服務(wù)器的連接等待數(shù)量以及等待時間,每次只放行少量用戶,讓更多的用戶處于假排隊的狀態(tài)。
例如tomcat的配置:
其中最后兩個參數(shù)意義如下:
maxThreads:tomcat起動的最大線程數(shù),即同時處理的任務(wù)個數(shù),默認值為200
acceptCount:當(dāng)tomcat起動的線程數(shù)達到最大時,接受排隊的請求個數(shù),默認值為100
這兩個值如何起作用,請看下面三種情況
情況1:接受一個請求,此時tomcat起動的線程數(shù)沒有到達maxThreads,tomcat會起動一個線程來處理此請求。
情況2:接受一個請求,此時tomcat起動的線程數(shù)已經(jīng)到達maxThreads,tomcat會把此請求放入等待隊列,等待空閑線程。
情況3:接受一個請求,此時tomcat起動的線程數(shù)已經(jīng)到達maxThreads,等待隊列中的請求個數(shù)也達到了acceptCount,此時tomcat會直接拒絕此次請求,返回connection refused。
2. 頁面靜態(tài)化
首先我們可以使用Freemarker對頁面進行靜態(tài)化,讓用戶減少跟后端服務(wù)器之間的交互。這樣就能降低服務(wù)器的壓力,如果條件允許我們可以采用CDN加速。
Freemarker的原理如下圖,模板+數(shù)據(jù)通過Freemarker可以生成靜態(tài)頁面。
CDN是將源站內(nèi)容分發(fā)至最接近用戶的節(jié)點,使用戶可就近取得所需內(nèi)容,提高用戶訪問的響應(yīng)速度和成功率。
例如下圖:北京網(wǎng)民會自動訪問到離自己最近并且速度最快的服務(wù)器的資源。
3. 引入Redis
限流和靜態(tài)化都是為了減輕服務(wù)器后端的壓力,但是最終用戶的請求還是會落到服務(wù)器中,為了增加用戶的體驗度,我們也應(yīng)加快相應(yīng)速度。后端代碼和數(shù)據(jù)庫之間的交互會降低相應(yīng)速度,所以我們可以采用Redis來進行數(shù)據(jù)的高速讀取。
Redis是一款極其優(yōu)秀的內(nèi)存級別的NoSql數(shù)據(jù)庫,單線程下讀寫速度能達到5w/s。所以我們在很多情況下都能利用Redis去解決高速讀取的問題。
特別是庫存量的超賣現(xiàn)象,我們可以在開始秒殺的時候,把總的庫存量存入Redis中,每當(dāng)用戶來搶購時,利用String類型的decr方法去減一,如果減一成功就視認為搶夠成功,并把用戶和商品信息存入Redis的訂單條目中,當(dāng)最終搶購結(jié)束時,我們再一并把Redis的訂單信息存入到數(shù)據(jù)庫中。
代碼參考:
四、總結(jié)
通過上述3種方案可以解決大部分場景下的秒殺問題,當(dāng)然高并發(fā)下也會出現(xiàn)更多的意外的狀況,那么我們可以針對自己的業(yè)務(wù),資源的調(diào)度進行更多方位的嘗試,找到最適合自己的解決方案。
猜你喜歡:
Java進階之JVM垃圾回收機制視頻教程