“秒殺”這個(gè)詞在電商行業(yè)中出現(xiàn)的頻率較高捶惜,如京東或者淘寶平臺(tái)的各種“秒殺”活動(dòng)制轰,最典型的就是“雙11搶購(gòu)”。
“秒殺”是指在有限的時(shí)間內(nèi)對(duì)有限的商品數(shù)量進(jìn)行搶購(gòu)的一種行為潜秋,這是商家以“低價(jià)量少”的商品來獲取用戶的一種營(yíng)銷手段。
需求分析
- 功能性需求
其實(shí)胎许,整個(gè)秒殺的業(yè)務(wù)場(chǎng)景并不復(fù)雜峻呛,可即查看參與秒殺的商品信息,加上購(gòu)買和支付的動(dòng)作辜窑,如下圖所示钩述。
秒殺業(yè)務(wù)場(chǎng)景最大的挑戰(zhàn)在于3點(diǎn):
- 瞬時(shí)
- 流量巨大
- 數(shù)量有限
同時(shí),在保證高并發(fā)流量承接的前提下穆碎,為了增強(qiáng)用戶的體驗(yàn)和活動(dòng)規(guī)則的公平性牙勘,以及防止遭到惡意破壞等,特此增加如下需求:
(1)用戶在秒殺頁(yè)面無需一直刷新“搶購(gòu)”按鈕,待秒殺活動(dòng)開始時(shí)方面,按鈕自動(dòng)點(diǎn)亮放钦。
(2)在公平以及防止惡意破壞的原則下,在下單之前增加驗(yàn)證碼的錄入恭金,或者答題的相關(guān)環(huán)節(jié)操禀。
(3)庫(kù)存不能出現(xiàn)問題,即不多扣也不少扣横腿。
(4)整個(gè)秒殺活動(dòng)過程持續(xù)10分鐘颓屑。
- 性能指標(biāo)預(yù)估
通過秒殺的需求描述可得出,當(dāng)前秒殺活動(dòng)主要需要預(yù)估三塊的性能指標(biāo):存儲(chǔ)容量耿焊、并發(fā)量揪惦、網(wǎng)絡(luò)帶寬。
- 存儲(chǔ)容量
由于是秒殺活動(dòng)搀别,且參與的商品基本都是低價(jià)高性價(jià)比的丹擎,數(shù)量是非常有限的。所以歇父,在訂單存儲(chǔ)上基本不用去過多考慮。 - 并發(fā)量
針對(duì)5000萬用戶平均每人訪問2次再愈,則并發(fā)量為每秒16.7萬左右(5000w2/1060),在預(yù)留一部分榜苫,可以預(yù)估到每秒25萬左右(也可以進(jìn)行double下)。 - 網(wǎng)絡(luò)帶寬
在帶寬方面翎冲,需要進(jìn)行相關(guān)優(yōu)化垂睬,采取數(shù)據(jù)傳輸越少越好,假設(shè)單條傳輸在0.5KB抗悍,則根據(jù)并發(fā)量預(yù)估網(wǎng)絡(luò)帶寬為:977Mb左右(25w0.5KB=122MB8bit=977Mb)驹饺。
- 非功能性需求
做任何系統(tǒng)都要考慮非功能性需求,特別是公司的核心系統(tǒng)缴渊,當(dāng)前秒殺業(yè)務(wù)系統(tǒng)非功能性需求
主要體現(xiàn)在如下幾點(diǎn):
高可用赏壹,在秒殺活動(dòng)的整個(gè)持續(xù)期間內(nèi),都能對(duì)用戶提供服務(wù)衔沼。
高性能蝌借,讓每個(gè)用戶都能感受到極快的秒殺響應(yīng),不能出現(xiàn)大批量用戶延遲較高的現(xiàn)象指蚁。
可擴(kuò)展菩佑,當(dāng)流量比預(yù)期更高時(shí),有平滑擴(kuò)展的策略(也有部分產(chǎn)品設(shè)計(jì)成友好的拒絕策略)凝化。
概要設(shè)計(jì)
通過對(duì)秒殺業(yè)務(wù)的本身認(rèn)知以及上面提到的秒殺業(yè)務(wù)需求稍坯,本次秒殺系統(tǒng)需要著重設(shè)計(jì)如下幾點(diǎn):
(1)動(dòng)靜分離:如何保證用戶在不刷新頁(yè)面的情況下,依然能進(jìn)行秒殺相關(guān)數(shù)據(jù)的獲取且不會(huì)耽誤秒殺活動(dòng)的開始搓劫。
(2)流量分層瞧哟,針對(duì)巨大流量袜蚕,如何進(jìn)行有效的防控,以免造成后臺(tái)服務(wù)的不堪重負(fù)绢涡,以及如何避免前端頁(yè)面的卡死牲剃。
(3)高可用:如何確保后臺(tái)持續(xù)提供服務(wù)。
(4)扣減庫(kù)存:如何有效扣減庫(kù)存雄可。
(5)系統(tǒng)架構(gòu)設(shè)計(jì)
詳細(xì)設(shè)計(jì)
- 動(dòng)靜分離
實(shí)施動(dòng)靜分離架構(gòu)可以采用“分而治之”的辦法凿傅,即將動(dòng)態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)解耦,分別使用各自的架構(gòu)系統(tǒng)來承載對(duì)應(yīng)的流量:
對(duì)于靜態(tài)數(shù)據(jù)数苫,推薦縮短用戶請(qǐng)求路徑聪舒,因?yàn)槁窂皆蕉蹋L問速度也就越快虐急。另外箱残,即盡可能將靜態(tài)數(shù)據(jù)緩存起來。
對(duì)于動(dòng)態(tài)數(shù)據(jù)止吁,一般用戶端需要和服務(wù)端進(jìn)行交互才能獲取被辑,所以,請(qǐng)求路徑較長(zhǎng)敬惦,訪問速度會(huì)慢一點(diǎn)盼理。下圖展示了動(dòng)靜分離方案。
靜態(tài)數(shù)據(jù)訪問速度很快俄删,而動(dòng)態(tài)數(shù)據(jù)訪問速度較慢宏怔。那么試想下,可以將需要?jiǎng)討B(tài)獲取的數(shù)據(jù)給提前生成好畴椰,然后使用靜態(tài)頁(yè)面加速技術(shù)來訪問嗎臊诊?如果這樣可以,那動(dòng)態(tài)數(shù)據(jù)訪問的速度就變快了斜脂。
這樣是可以的抓艳,需要用到比較流行的“頁(yè)面靜態(tài)化”技術(shù)。頁(yè)面靜態(tài)化技術(shù)是指秽褒,直接緩存HTTP連接壶硅,而不僅是緩存數(shù)據(jù)。如下圖所示销斟,代理服務(wù)器根據(jù)請(qǐng)求的URL直接將HTTP對(duì)應(yīng)的響應(yīng)頭及響應(yīng)消息體返回庐椒,流程簡(jiǎn)潔且高效。
- 流量分層設(shè)計(jì)
流量分層主要體現(xiàn)在對(duì)于CDN層蚂踊、反向代理層约谈、后端服務(wù)層以及數(shù)據(jù)層流量進(jìn)行控制。
1)CDN層流量控制
由動(dòng)靜分離技術(shù)可以想到:應(yīng)盡量將盡可能多的數(shù)據(jù)提前生成,然后將其放入CDN節(jié)點(diǎn)緩存中(因?yàn)镃DN層在物理架構(gòu)上離用戶比較近)棱诱。
所以泼橘,如果絕大部分的流量都在這一層獲取數(shù)據(jù),則到達(dá)后端的流量會(huì)減少很多迈勋,如下圖所示炬灭。
圖片
2)反向代理層流量控制
在動(dòng)靜分離方案中,講到通過“頁(yè)面靜態(tài)化技術(shù)”加速動(dòng)態(tài)數(shù)據(jù)的獲取靡菇,即提前將動(dòng)態(tài)數(shù)據(jù)生成好重归,然后對(duì)其進(jìn)行靜態(tài)化處理。
所以厦凤,這里就可以依據(jù)頁(yè)面靜態(tài)化加速技術(shù)鼻吮,通過后端服務(wù)Job的方式定時(shí)提前生成前端需要靜態(tài)的數(shù)據(jù);然后较鼓,將其發(fā)送到內(nèi)容分發(fā)服務(wù)上椎木;最后,分發(fā)服務(wù)會(huì)將這些靜態(tài)化頁(yè)面數(shù)據(jù)分發(fā)到所有的反向代理服務(wù)器上博烂,如下圖所示香椎。
圖片
在“秒殺”業(yè)務(wù)中,活動(dòng)詳情頁(yè)上有一個(gè)倒計(jì)時(shí)的模塊脖母,用戶可以看到當(dāng)前“秒殺”活動(dòng)還剩余多少時(shí)間開始士鸥。
這種邏輯簡(jiǎn)單的功能可以直接使用Nginx來實(shí)現(xiàn):利用nginx-lua插件,使用lua腳本獲取當(dāng)前Nginx服務(wù)器的時(shí)間進(jìn)行計(jì)算倒計(jì)時(shí)谆级。
另外,商品庫(kù)存數(shù)據(jù)也可以通過Nginx直接訪問分布式緩存來獲取讼积,如下圖所示肥照。
圖片
“秒殺”業(yè)務(wù)中的商品價(jià)格很低,對(duì)于用戶有很大的吸引力勤众,所以可能會(huì)有人利用“秒殺器”進(jìn)行不公平競(jìng)爭(zhēng)舆绎,且有可能存在競(jìng)爭(zhēng)對(duì)手惡意刷請(qǐng)求的情況。
如果存在這樣的情況们颜,那本次活動(dòng)就是有風(fēng)險(xiǎn)的吕朵,萬一被惡意流量獨(dú)占了庫(kù)存,則會(huì)導(dǎo)致正常用戶不能搶購(gòu)商品窥突,也有可能這種惡意的請(qǐng)求會(huì)對(duì)后端系統(tǒng)造成嚴(yán)重沖擊努溃,甚至造成后端系統(tǒng)癱瘓。
對(duì)于這種惡意請(qǐng)求阻问,最好有一套機(jī)制能提前感知梧税,并將惡意請(qǐng)求提前封存。可以在Nginx層中控制第队;也可以在Nginx中配置用戶的訪問頻率(例如每分鐘只能訪問10次)哮塞;還可以使用Lua腳本編寫一些簡(jiǎn)單業(yè)務(wù)邏輯的接口,例如凳谦,通過調(diào)用接口直接封掉指定IP地址或UserAgent的請(qǐng)求忆畅。
3)后端服務(wù)層流量控制
對(duì)于服務(wù)層的流量控制,有以下幾點(diǎn)建議:
在程序開發(fā)上尸执,代碼獨(dú)立家凯,不要與平臺(tái)其他項(xiàng)目一起。
在部署時(shí)剔交,應(yīng)用獨(dú)立部署肆饶,分散流量,避免不合適的流量影響主體業(yè)務(wù)岖常。
使用獨(dú)立域名驯镊,或者按照一定的URL規(guī)則在反向代理層進(jìn)行路由。
做好系統(tǒng)保護(hù)和限流竭鞍,進(jìn)一步減少不必要的流量板惑。
當(dāng)“到達(dá)系統(tǒng)中的請(qǐng)求數(shù)”明顯大于“系統(tǒng)能夠處理的最大請(qǐng)求數(shù)”時(shí),可以直接拒絕這些多余的請(qǐng)求偎快,直接返回“秒殺”活動(dòng)結(jié)束的信息冯乘。例如,活動(dòng)開始時(shí)的商品庫(kù)存是100晒夹,目前庫(kù)存只剩50了裆馒,如果“每臺(tái)服務(wù)器待處理的請(qǐng)求數(shù)”已經(jīng)超過“商品總庫(kù)存數(shù)(100)”了,則可以直接終止掉多余的請(qǐng)求丐怯。
4)數(shù)據(jù)庫(kù)層流量控制
對(duì)于請(qǐng)求到數(shù)據(jù)中的流量喷好,寫入的流量就是真正下單成功的流量,即需要扣減庫(kù)存的動(dòng)作读跷。有如下建議:
如果不是臨時(shí)的活動(dòng)梗搅,則建議使用獨(dú)立的數(shù)據(jù)庫(kù)作為“秒殺”活動(dòng)的數(shù)據(jù)庫(kù)。
將數(shù)據(jù)庫(kù)配置成讀寫分離效览。
嘗試去除行鎖无切。
對(duì)于數(shù)據(jù)庫(kù)行鎖的優(yōu)化,可以通過將商品進(jìn)行拆分來實(shí)現(xiàn)——增加ID丐枉,如下圖所示哆键。對(duì)于單一的“秒殺”活動(dòng)這會(huì)得到顯著效果。
從流量分層控制方案可看出矛洞,瞬時(shí)流量就像被漏斗過濾了似的洼哎,應(yīng)盡量將數(shù)據(jù)和請(qǐng)求量一層一層地過濾掉烫映。這種流量分層控制核心思想:在不同的層級(jí)中盡可能地過濾掉無效的請(qǐng)求,到達(dá)“倒三角”最末端的請(qǐng)求才是有效的請(qǐng)求噩峦。
5)高可用
在系統(tǒng)設(shè)計(jì)時(shí)想要做到高可用锭沟,避免單節(jié)點(diǎn)的一個(gè)小妙招:將服務(wù)無狀態(tài)化。如果無法完全無狀態(tài)化(如存儲(chǔ)系統(tǒng))识补,則可以通過冗余多個(gè)備份節(jié)點(diǎn)的方案來避免單節(jié)點(diǎn)族淮。
由于篇幅原因,高可用此處就不再贅述凭涂,大家可以查看《高并發(fā)系統(tǒng)實(shí)戰(zhàn)派》一書里面針對(duì)高并發(fā)系統(tǒng)的真實(shí)設(shè)計(jì)案例祝辣,毫無保留的分享出了企業(yè)級(jí)高并發(fā)系統(tǒng)實(shí)戰(zhàn)。
- 扣減庫(kù)存設(shè)計(jì)
由于在“秒殺”場(chǎng)景中商品一般優(yōu)惠力度很大切油,對(duì)用戶很具有吸引力蝙斜,所以,在這種場(chǎng)景中使用“下單扣庫(kù)存”方式更為合適澎胡。
在“秒殺”場(chǎng)景中孕荠,大部分用戶抱著“搶到就是賺到”的想法,基本都會(huì)去付款的攻谁,但如果真有競(jìng)爭(zhēng)對(duì)手惡意下單不付款稚伍,那我們?cè)撛趺崔k?前面在流量管控中已經(jīng)說到戚宦,可以對(duì)請(qǐng)求日志進(jìn)行實(shí)時(shí)分析个曙,讓風(fēng)控系統(tǒng)選擇出惡意用戶,然后將其封停受楼。
在“秒殺”場(chǎng)景中垦搬,通過流量分層控制可以分層管控大量的“讀”請(qǐng)求。但是艳汽,依然會(huì)有很大的流量進(jìn)入真正的下單邏輯悼沿。對(duì)于這么大的流量,除前面說的數(shù)據(jù)庫(kù)隔離外骚灸,還需要進(jìn)一步優(yōu)化庫(kù)存,否則數(shù)據(jù)庫(kù)讀/寫依然是系統(tǒng)的瓶頸慌植。
接下來看看如何優(yōu)化大流量“秒殺”場(chǎng)景中的庫(kù)存數(shù)量扣減操作甚牲。
1)利用緩存技術(shù)
在“秒殺”場(chǎng)景中,如果只是一個(gè)扣減庫(kù)存數(shù)量這樣的簡(jiǎn)單流程蝶柿,則可以先將庫(kù)存數(shù)量直接放在緩存中丈钙,然后用分布式緩存(如Redis)的超高性能去應(yīng)對(duì)這種瞬時(shí)流量洪峰下的系統(tǒng)挑戰(zhàn)。
使用緩存是存在一定風(fēng)險(xiǎn)的交汤,比如雏赦,緩存節(jié)點(diǎn)出現(xiàn)了異常劫笙,那庫(kù)存數(shù)量該怎么算?
使用緩存星岗,不僅要考慮分布式緩存高可用(如何設(shè)計(jì)可以查看我的新書“高并發(fā)系統(tǒng)實(shí)戰(zhàn)派”)填大,還要考慮各種限流容錯(cuò)機(jī)制,以確保分布式緩存對(duì)外提供服務(wù)俏橘。
2)異步處理技術(shù)
如果是復(fù)雜的扣減庫(kù)存(如涉及商品信息本身或牽連其他系統(tǒng))允华,則建議使用數(shù)據(jù)庫(kù)進(jìn)行庫(kù)存數(shù)量的扣減,可以使用異步的方式來應(yīng)對(duì)這種高并發(fā)的庫(kù)存的更新寥掐。
①在用戶下單時(shí)靴寂,不立刻生成訂單,而是將所有訂單依次放入隊(duì)列召耘。
②下單模塊依據(jù)自身的處理速度百炬,從隊(duì)列中依次獲取訂單進(jìn)行“下單扣庫(kù)存”操作。
③在訂單生成成功后污它,用戶即可進(jìn)行支付操作了剖踊。
這種方式是針對(duì)“秒殺”場(chǎng)景的,依據(jù)“先到先得”原則來保證公平公正轨蛤,所有用戶都可以搶購(gòu)蜜宪,然后等待訂單處理,最后生成訂單(如果庫(kù)存不足祥山,則生成訂單失斊匝椤)评架。
這樣的邏輯腾供,對(duì)用戶來說體驗(yàn)不是很差。
那些技術(shù)
(1)數(shù)據(jù)的靜態(tài)化的技術(shù)
用來應(yīng)對(duì)高并發(fā)讀的請(qǐng)求玻驻,主要涉及以下內(nèi)容供常,這些在《高并發(fā)系統(tǒng)實(shí)戰(zhàn)派》一書中詳細(xì)分享了真實(shí)使用場(chǎng)景已經(jīng)技術(shù)方案:
各層級(jí)緩存的處理(即多級(jí)緩存的技術(shù))
分布式緩存技術(shù)
(2)負(fù)載均衡反向代理技術(shù)
LVS
Nginx
(3)異步處理技術(shù)
消息隊(duì)列技術(shù)
排隊(duì)系統(tǒng)技術(shù)
(4)系統(tǒng)架構(gòu)設(shè)計(jì)技術(shù)
系統(tǒng)模塊化劃分
微服務(wù)架構(gòu)思想
(5)系統(tǒng)監(jiān)控技術(shù)
日志監(jiān)控
服務(wù)監(jiān)控