新聞中心
秒殺活動(dòng)架構(gòu)
秒殺活動(dòng)是電商項(xiàng)目中常出現(xiàn)的活動(dòng)。比如演唱會(huì)門票搶購(gòu),京東淘寶秒殺商品搶購(gòu)。在搶購(gòu)那一刻,會(huì)有大量用戶同時(shí)高并發(fā)的請(qǐng)求應(yīng)用系統(tǒng),可能會(huì)達(dá)到每秒幾萬、幾十萬的請(qǐng)求。如果系統(tǒng)無法處理這么高的請(qǐng)求,那么就會(huì)崩潰,從而導(dǎo)致系統(tǒng)不可用。

蒲縣網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)于2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。
對(duì)于秒殺活動(dòng)來說,要求系統(tǒng)不會(huì)出現(xiàn)壓力過大而崩潰的場(chǎng)景,并且不會(huì)出現(xiàn)超賣、少賣的情形。
所以秒殺系統(tǒng)中我們需要思考:
- “系統(tǒng)如何扛住高并發(fā)請(qǐng)求系統(tǒng)如何保證不超賣等問題”
對(duì)此我的解決思路是:
- “服務(wù)端中,使用緩存減少對(duì)數(shù)據(jù)庫(kù)訪問將請(qǐng)求流量攔截在上游,可以使用限流技術(shù)使用分布式隊(duì)列進(jìn)行流量削峰,將并發(fā)串行化”
秒殺架構(gòu)圖
秒殺架構(gòu)圖如上。
客戶端
用戶發(fā)起請(qǐng)求的端口,目前電商項(xiàng)目秒殺活動(dòng)主要客戶端有微信小程序、H5(瀏覽器)、各平臺(tái)app(比如Android、iOS、Windows)。我們可以在客戶端實(shí)現(xiàn)限流機(jī)制,這樣就可以避免用戶發(fā)送大量請(qǐng)求到服務(wù)端。
客戶端的限流可以控制按鈕的點(diǎn)擊頻率,比如對(duì)按鈕置灰。
反向代理
我們可以使用Nginx實(shí)現(xiàn)請(qǐng)求分流,通過負(fù)載均衡將請(qǐng)求均勻的分布到不同的Web節(jié)點(diǎn)中。
Nginx也可以作為限流使用。Nginx可以控制單位時(shí)間內(nèi)的請(qǐng)求數(shù),限制同一時(shí)間的連接數(shù)。
API網(wǎng)關(guān)
如果實(shí)際參與秒殺活動(dòng)的用戶非常大,并發(fā)請(qǐng)求非常大。我們就需要在API網(wǎng)關(guān)這一層中進(jìn)行限流,這里可以實(shí)現(xiàn)對(duì)單個(gè)Web節(jié)點(diǎn)實(shí)現(xiàn)每秒最大請(qǐng)求數(shù)限制。
我們也可以控制每個(gè)用戶的最大請(qǐng)求數(shù),通過Redis記錄每個(gè)用戶的請(qǐng)求數(shù)。
緩存
在服務(wù)層業(yè)務(wù)中,為減少對(duì)數(shù)據(jù)庫(kù)的訪問,需要進(jìn)行緩存設(shè)計(jì),我們可以使用本地緩存,或者分布式緩存。
隊(duì)列
隊(duì)列主要是用來實(shí)現(xiàn)流量的削峰填谷,我們可以使用RocketMQ、Kafka等消息中間件作為分布式的隊(duì)列。
關(guān)于限流
秒殺系統(tǒng)中為什么需要限流?在秒殺活動(dòng)中商品庫(kù)存是有限的,而請(qǐng)求的用戶數(shù)量遠(yuǎn)遠(yuǎn)大于商品庫(kù)存數(shù)量。大部分的用戶請(qǐng)求實(shí)際上是無法搶到商品的無效流量。所以這部分流量可以攔截在上游進(jìn)行限流。
為了避免用戶采用腳本或者頻繁點(diǎn)擊發(fā)送大量請(qǐng)求,而導(dǎo)致其他用戶無法正常參加活動(dòng),我們也需要控制用戶每秒的請(qǐng)求量。
我們可從URI和用戶兩個(gè)方面實(shí)行限流。
URI限流示例代碼:
用戶維度的限流示例代碼:
我們獲取URI維度的限流器對(duì)象uriLimiter,和用戶維度的限流器對(duì)象userLimiter。如果tryAcquire()成功獲得許可,則請(qǐng)求通過,進(jìn)入后續(xù)業(yè)務(wù)。否則直接報(bào)異常,前端界面作相應(yīng)的友好提示。
在緩存中扣減庫(kù)存
使用Redis來存儲(chǔ)庫(kù)存數(shù)量,當(dāng)用戶發(fā)起搶購(gòu)請(qǐng)求時(shí),先判斷Redis中的庫(kù)存是否可用。如果可用,將搶購(gòu)請(qǐng)求放入分布式隊(duì)列中,采用異步方式處理后續(xù)操作,并完成下單。同時(shí)在Redis中作庫(kù)存扣減。
示例代碼如下:
先做庫(kù)存扣減并獲取扣減后的庫(kù)存數(shù)量,如果庫(kù)存數(shù)量大于或等于0,將訂單創(chuàng)建請(qǐng)求發(fā)送到mq。否則返回?fù)屬?gòu)失敗的信息。
消費(fèi)者創(chuàng)建訂單:
關(guān)于如何初始化庫(kù)存?
在搶購(gòu)活動(dòng)開始前,有運(yùn)營(yíng)人員在后臺(tái)手動(dòng)將商品庫(kù)存從數(shù)據(jù)庫(kù)同步到緩存中。庫(kù)存的扣減在緩存中進(jìn)行扣減。
利用Redis單線程特性可以實(shí)現(xiàn)多線程下安全的庫(kù)存更新。如果查詢緩存中的值時(shí),發(fā)現(xiàn)沒有,需要從數(shù)據(jù)庫(kù)中查詢,然后再同步到緩存中,這個(gè)過程需要加鎖。
示例代碼如下:
總結(jié)
秒殺設(shè)計(jì)是典型的高并發(fā)系統(tǒng),關(guān)于秒殺系統(tǒng)的設(shè)計(jì),經(jīng)常會(huì)在面試中被問到。在設(shè)計(jì)秒殺系統(tǒng)時(shí),我們需要考慮:
- “請(qǐng)求分流-通過負(fù)載均衡實(shí)現(xiàn)限流-采用漏斗算法(如guava的RateLimiter),信號(hào)量Semaphore,Redis計(jì)數(shù)等實(shí)現(xiàn)Redis扣減庫(kù)存-減少對(duì)數(shù)據(jù)庫(kù)的訪問流量削峰-分布式隊(duì)列實(shí)現(xiàn)”
文章標(biāo)題:一次阿里面試,我被問到了如何設(shè)計(jì)秒殺系統(tǒng)
地址分享:http://m.fisionsoft.com.cn/article/ccssshi.html


咨詢
建站咨詢
