業(yè)務(wù)描述
現(xiàn)在電商企業(yè)一大把,除了某寶悯仙、某東等大鱷龄毡,還有各種街、某說雁比、某會(huì)、沒有品等創(chuàng)業(yè)明星撤嫩,以及蘇寧偎捎、國(guó)美等傳統(tǒng)企業(yè)的電商部門,可謂百花齊放序攘。電商以運(yùn)營(yíng)為基礎(chǔ)茴她,各種活動(dòng)、購(gòu)物節(jié)層出不窮程奠,秒殺可謂是其中的一朵奇葩——價(jià)格低到不要不要的丈牢。由于好貨超低價(jià)(大多是一元),秒殺會(huì)吸引大量的尖峰流量聚集瞄沙,對(duì)架構(gòu)師來說是一大挑戰(zhàn)己沛。 只談技術(shù)上的業(yè)務(wù)描述慌核,秒殺一般分為秒殺前、秒殺中申尼、秒殺后三個(gè)階段垮卓,各個(gè)階段的需求如下:
秒殺前,用戶訪問秒殺寶貝描述頁(yè)师幕,不斷刷新粟按,等待秒殺開始。
秒殺中霹粥,用戶點(diǎn)擊秒殺按鈕灭将,洪水般的流量瞬間涌入系統(tǒng),都想走在前面后控,搶到寶貝庙曙。
秒殺后,秒殺結(jié)束忆蚀,商品已被搶完或者秒殺時(shí)間已過矾利,用戶訪問秒殺結(jié)束頁(yè)面,整個(gè)秒殺階段結(jié)束馋袜。
挑戰(zhàn)在哪
秒殺前男旗,大量用戶頻發(fā)刷新秒殺頁(yè)面,都想第一個(gè)看到秒殺開始欣鳖,越臨近開始時(shí)間察皇,刷新越頻繁,這時(shí)候?qū)ο到y(tǒng)會(huì)有巨大的讀壓力泽台。 秒殺中什荣,用戶的秒殺請(qǐng)求短時(shí)間內(nèi)持續(xù)涌入,前端訪問量暴增怀酷,并且會(huì)牽扯到寫庫(kù)的需求稻爬,還有在對(duì)于單一熱點(diǎn)商品庫(kù)存判斷和遞減,由于寫庫(kù)是排他操作蜕依,一個(gè)一個(gè)排隊(duì)處理桅锄,數(shù)據(jù)庫(kù)寫壓力很大。 秒殺后样眠,和秒殺前差不多友瘤,短時(shí)間內(nèi)單頁(yè)面很多用戶訪問,但時(shí)間一過檐束,頁(yè)面就沒有訪問量了辫秧。
所以,方案呢
對(duì)于秒殺前后單頁(yè)面的大量訪問被丧,處理起來很簡(jiǎn)單盟戏,提前預(yù)熱把秒殺頁(yè)面放入cdn绪妹,大量的請(qǐng)求就可以抗住了。這里有一些需要注意的點(diǎn)抓半,一是cdn放的是靜態(tài)頁(yè)面喂急,秒殺需要判斷秒殺開始,這個(gè)可以使用動(dòng)態(tài)加載js的方式(網(wǎng)頁(yè))笛求,從cdn去請(qǐng)求一個(gè)js(秒殺開始后再生成)廊移,該js負(fù)責(zé)跳轉(zhuǎn)到秒殺頁(yè)面(秒殺開始后再生成,避免作弊)探入,如果是app狡孔,可以用webview或者請(qǐng)求一個(gè)cdn上的文件也是可以的。有人說為什么不直接請(qǐng)求接口來獲取秒殺開始標(biāo)識(shí)蜂嗽,當(dāng)然是可以的苗膝,但是cdn是部署到全國(guó)各地的,如果請(qǐng)求服務(wù)器植旧,這部分量會(huì)占用一部分服務(wù)器資源辱揭,秒殺誒,能節(jié)約資源來進(jìn)行后續(xù)請(qǐng)求就節(jié)約啊病附,不然掛了不好看啊问窃。二是怎么判斷秒殺是否開始,秒殺基本都是約定好在某個(gè)時(shí)間點(diǎn)開始完沪,所以一種直接的想法就是靠時(shí)間咯域庇。這的確是一種做法,但不是很好覆积,首先是因?yàn)槊霘榱朔稚⒘刻螅鄠€(gè)商品的秒殺就算是一個(gè)時(shí)間點(diǎn),也應(yīng)該分開進(jìn)行宽档,這樣緩解系統(tǒng)壓力尉姨;其次就是為了公平性,這個(gè)開始時(shí)間會(huì)在一定范圍內(nèi)有隨機(jī)性吗冤,這樣由于用戶看到頁(yè)面的時(shí)間隨機(jī)又厉,不用只拼網(wǎng)速啦,人品也是有用的欣孤;還有就是秒殺開始后還有其他工作要做馋没,比如刷cdn放js昔逗,生成秒殺頁(yè)面等降传,時(shí)間在分布式系統(tǒng)里是最不靠譜的了(服務(wù)器時(shí)間是有差別的),會(huì)導(dǎo)致數(shù)據(jù)問題(比如js生成了勾怒,秒殺頁(yè)面還沒有出來婆排,用戶一堆404)声旺,用戶會(huì)罵娘的。所以一般會(huì)抽象一個(gè)發(fā)令器出來(是的段只,程序來源于生活腮猖。。赞枕。)澈缺,秒殺系統(tǒng)激活發(fā)令器,秒殺開始炕婶,下游其它業(yè)務(wù)開始處理姐赡,這里可以定義這些業(yè)務(wù)的處理順序,秒殺系統(tǒng)里可以配置何時(shí)發(fā)令柠掂,當(dāng)然也可以有隨機(jī)的規(guī)則项滑。消息中間件出現(xiàn)了,這里發(fā)令器發(fā)令后涯贞,下游的業(yè)務(wù)就是通過消息中間件得到的秒殺開始的信號(hào)G箍瘛!很多解決不了的問題往往是因?yàn)橐暯遣粚?duì)宋渔,以更高的視角看問題州疾,很多問題往往只缺一個(gè)抽象。
秒殺中的最大壓力就是對(duì)商品庫(kù)存的并發(fā)爭(zhēng)搶傻谁,就像商場(chǎng)大促銷孝治,就那么兩件,一堆大媽沖上去搶审磁,各個(gè)身懷絕技谈飒,商場(chǎng)導(dǎo)購(gòu)小妹沒點(diǎn)武藝還真是抗不住。這時(shí)候可以參考之前文章中的異步減庫(kù)存的形式來做态蒂,只是這里是異步下訂單杭措。說具體方案之前,先看看這個(gè)業(yè)務(wù)場(chǎng)景要做什么钾恢?其實(shí)就是在解決一萬(wàn)個(gè)人同時(shí)拿著錢來東西手素,但是東西只有十件,你賣給誰(shuí)的問題瘩蚪,只要沒給錢泉懦,那我東西不給你就沒問題,給了錢就必須拿到東西疹瘦。所以這里我們可以對(duì)來買東西的人強(qiáng)制他們排隊(duì)崩哩,先到先得,并且排隊(duì)的數(shù)據(jù)少量丟失是可以接受的,后面拍著那么多人呢邓嘹,不怕賣不完酣栈。那最后的方案就是,用戶點(diǎn)擊秒殺按鈕后汹押,加入秒殺隊(duì)列(限制長(zhǎng)度)矿筝,加入成功則告知正在秒殺,否則直接跳到秒殺結(jié)束頁(yè)面棚贾。對(duì)于秒殺隊(duì)列中的用戶窖维,則進(jìn)行寫訂單減庫(kù)存處理處理,并且記錄成功與失敗妙痹,商品秒殺完成后陈辱,標(biāo)記秒殺結(jié)束,并且可以清空秒殺隊(duì)列细诸,避免后面重復(fù)判斷和處理沛贪。用戶端輪詢(可以采用長(zhǎng)輪詢,時(shí)效性好)結(jié)果震贵,如果秒殺結(jié)束并且自己沒有秒殺成功利赋,則跳轉(zhuǎn)到秒殺結(jié)束頁(yè)面,否則繼續(xù)等待猩系,如果秒殺成功則跳轉(zhuǎn)到秒殺成功頁(yè)面媚送,支付就是后面的事情了。這里有幾個(gè)點(diǎn)需要關(guān)注寇甸,一是作弊塘偎,就是驗(yàn)證碼,各種策略各種造型的驗(yàn)證碼拿霉;二是時(shí)效性吟秩,秒殺完后一段時(shí)間(比如半個(gè)小時(shí))沒付款,應(yīng)該將該筆秒殺標(biāo)記無效绽淘,并且把庫(kù)存回補(bǔ)涵防。消息中間件再次大顯身手,秒殺隊(duì)列沪铭,這里需要消息中間件提供限長(zhǎng)隊(duì)列功能(不限長(zhǎng)壮池,先查詢?cè)偃腙?duì)也是可以的,只是要把握好這個(gè)時(shí)間間隔可能加入的多余數(shù)據(jù)對(duì)消息中間件的影響)杀怠,清空隊(duì)列功能(沒有也可以椰憋,只是不能更快的釋放壓力)。當(dāng)然除了這些赔退,還有限流功能橙依,接入層只允許系統(tǒng)可負(fù)載流量進(jìn)入,超過一定負(fù)載就采取措施緩解流量進(jìn)入(比如驗(yàn)證碼。票编。。)卵渴』塾颍可以看到,對(duì)于秒殺中功能浪读,基本就是采取逐級(jí)降低流量的方法(大流量系統(tǒng)的重要思路)昔榴,只讓不過分高于有效流量的流量進(jìn)入后端真正的業(yè)務(wù)系統(tǒng),保證業(yè)務(wù)系統(tǒng)不宕機(jī)碘橘。還有一個(gè)原則就是讀比寫更容易擴(kuò)展互订,無業(yè)務(wù)系統(tǒng)比業(yè)務(wù)系統(tǒng)更容易擴(kuò)展,所以應(yīng)該化寫為讀(下訂單變?yōu)椴樵冇唵危┒徊穑档蜆I(yè)務(wù)系統(tǒng)壓力(前端接入層攔截?zé)o效流量)仰禽。
秒殺后的方案和秒殺前差不多,不再贅述纺蛆。
最后說兩句
本質(zhì)吐葵,本質(zhì),本質(zhì)桥氏! 抓住本質(zhì)看問題温峭,不要為了解決問題而解決問題!
本文首發(fā)來自架構(gòu)小站——淺談秒殺系統(tǒng)