秒殺場景

“秒殺”這個詞在電商行業(yè)中出現(xiàn)的頻率較高,如京東或者淘寶平臺的各種“秒殺”活動,最典型的就是“雙11搶購”。
“秒殺”是指在有限的時間內(nèi)對有限的商品數(shù)量進行搶購的一種行為,這是商家以“低價量少”的商品來獲取用戶的一種營銷手段。

需求分析

  1. 功能性需求
    其實,整個秒殺的業(yè)務(wù)場景并不復(fù)雜,可即查看參與秒殺的商品信息,加上購買和支付的動作,如下圖所示。

秒殺業(yè)務(wù)場景最大的挑戰(zhàn)在于3點:

  • 瞬時
  • 流量巨大
  • 數(shù)量有限
    同時,在保證高并發(fā)流量承接的前提下,為了增強用戶的體驗和活動規(guī)則的公平性,以及防止遭到惡意破壞等,特此增加如下需求:
    (1)用戶在秒殺頁面無需一直刷新“搶購”按鈕,待秒殺活動開始時,按鈕自動點亮。

(2)在公平以及防止惡意破壞的原則下,在下單之前增加驗證碼的錄入,或者答題的相關(guān)環(huán)節(jié)。

(3)庫存不能出現(xiàn)問題,即不多扣也不少扣。

(4)整個秒殺活動過程持續(xù)10分鐘。

  1. 性能指標預(yù)估
    通過秒殺的需求描述可得出,當前秒殺活動主要需要預(yù)估三塊的性能指標:存儲容量、并發(fā)量、網(wǎng)絡(luò)帶寬。
  • 存儲容量
    由于是秒殺活動,且參與的商品基本都是低價高性價比的,數(shù)量是非常有限的。所以,在訂單存儲上基本不用去過多考慮。
  • 并發(fā)量
    針對5000萬用戶平均每人訪問2次,則并發(fā)量為每秒16.7萬左右(5000w2/1060),在預(yù)留一部分,可以預(yù)估到每秒25萬左右(也可以進行double下)。
  • 網(wǎng)絡(luò)帶寬
    在帶寬方面,需要進行相關(guān)優(yōu)化,采取數(shù)據(jù)傳輸越少越好,假設(shè)單條傳輸在0.5KB,則根據(jù)并發(fā)量預(yù)估網(wǎng)絡(luò)帶寬為:977Mb左右(25w0.5KB=122MB8bit=977Mb)。
  1. 非功能性需求
    做任何系統(tǒng)都要考慮非功能性需求,特別是公司的核心系統(tǒng),當前秒殺業(yè)務(wù)系統(tǒng)非功能性需求
    主要體現(xiàn)在如下幾點:
  • 高可用,在秒殺活動的整個持續(xù)期間內(nèi),都能對用戶提供服務(wù)。

  • 高性能,讓每個用戶都能感受到極快的秒殺響應(yīng),不能出現(xiàn)大批量用戶延遲較高的現(xiàn)象。

  • 可擴展,當流量比預(yù)期更高時,有平滑擴展的策略(也有部分產(chǎn)品設(shè)計成友好的拒絕策略)。

概要設(shè)計

通過對秒殺業(yè)務(wù)的本身認知以及上面提到的秒殺業(yè)務(wù)需求,本次秒殺系統(tǒng)需要著重設(shè)計如下幾點:

(1)動靜分離:如何保證用戶在不刷新頁面的情況下,依然能進行秒殺相關(guān)數(shù)據(jù)的獲取且不會耽誤秒殺活動的開始。

(2)流量分層,針對巨大流量,如何進行有效的防控,以免造成后臺服務(wù)的不堪重負,以及如何避免前端頁面的卡死。

(3)高可用:如何確保后臺持續(xù)提供服務(wù)。

(4)扣減庫存:如何有效扣減庫存。

(5)系統(tǒng)架構(gòu)設(shè)計

詳細設(shè)計

  1. 動靜分離
    實施動靜分離架構(gòu)可以采用“分而治之”的辦法,即將動態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)解耦,分別使用各自的架構(gòu)系統(tǒng)來承載對應(yīng)的流量:

對于靜態(tài)數(shù)據(jù),推薦縮短用戶請求路徑,因為路徑越短,訪問速度也就越快。另外,即盡可能將靜態(tài)數(shù)據(jù)緩存起來。

對于動態(tài)數(shù)據(jù),一般用戶端需要和服務(wù)端進行交互才能獲取,所以,請求路徑較長,訪問速度會慢一點。下圖展示了動靜分離方案。

靜態(tài)數(shù)據(jù)訪問速度很快,而動態(tài)數(shù)據(jù)訪問速度較慢。那么試想下,可以將需要動態(tài)獲取的數(shù)據(jù)給提前生成好,然后使用靜態(tài)頁面加速技術(shù)來訪問嗎?如果這樣可以,那動態(tài)數(shù)據(jù)訪問的速度就變快了。

這樣是可以的,需要用到比較流行的“頁面靜態(tài)化”技術(shù)。頁面靜態(tài)化技術(shù)是指,直接緩存HTTP連接,而不僅是緩存數(shù)據(jù)。如下圖所示,代理服務(wù)器根據(jù)請求的URL直接將HTTP對應(yīng)的響應(yīng)頭及響應(yīng)消息體返回,流程簡潔且高效。

  1. 流量分層設(shè)計
    流量分層主要體現(xiàn)在對于CDN層、反向代理層、后端服務(wù)層以及數(shù)據(jù)層流量進行控制。

1)CDN層流量控制
由動靜分離技術(shù)可以想到:應(yīng)盡量將盡可能多的數(shù)據(jù)提前生成,然后將其放入CDN節(jié)點緩存中(因為CDN層在物理架構(gòu)上離用戶比較近)。

所以,如果絕大部分的流量都在這一層獲取數(shù)據(jù),則到達后端的流量會減少很多,如下圖所示。

圖片

2)反向代理層流量控制
在動靜分離方案中,講到通過“頁面靜態(tài)化技術(shù)”加速動態(tài)數(shù)據(jù)的獲取,即提前將動態(tài)數(shù)據(jù)生成好,然后對其進行靜態(tài)化處理。

所以,這里就可以依據(jù)頁面靜態(tài)化加速技術(shù),通過后端服務(wù)Job的方式定時提前生成前端需要靜態(tài)的數(shù)據(jù);然后,將其發(fā)送到內(nèi)容分發(fā)服務(wù)上;最后,分發(fā)服務(wù)會將這些靜態(tài)化頁面數(shù)據(jù)分發(fā)到所有的反向代理服務(wù)器上,如下圖所示。

圖片

在“秒殺”業(yè)務(wù)中,活動詳情頁上有一個倒計時的模塊,用戶可以看到當前“秒殺”活動還剩余多少時間開始。

這種邏輯簡單的功能可以直接使用Nginx來實現(xiàn):利用nginx-lua插件,使用lua腳本獲取當前Nginx服務(wù)器的時間進行計算倒計時。

另外,商品庫存數(shù)據(jù)也可以通過Nginx直接訪問分布式緩存來獲取,如下圖所示。

圖片

“秒殺”業(yè)務(wù)中的商品價格很低,對于用戶有很大的吸引力,所以可能會有人利用“秒殺器”進行不公平競爭,且有可能存在競爭對手惡意刷請求的情況。

如果存在這樣的情況,那本次活動就是有風(fēng)險的,萬一被惡意流量獨占了庫存,則會導(dǎo)致正常用戶不能搶購商品,也有可能這種惡意的請求會對后端系統(tǒng)造成嚴重沖擊,甚至造成后端系統(tǒng)癱瘓。

對于這種惡意請求,最好有一套機制能提前感知,并將惡意請求提前封存??梢栽贜ginx層中控制;也可以在Nginx中配置用戶的訪問頻率(例如每分鐘只能訪問10次);還可以使用Lua腳本編寫一些簡單業(yè)務(wù)邏輯的接口,例如,通過調(diào)用接口直接封掉指定IP地址或UserAgent的請求。

3)后端服務(wù)層流量控制
對于服務(wù)層的流量控制,有以下幾點建議:

在程序開發(fā)上,代碼獨立,不要與平臺其他項目一起。

在部署時,應(yīng)用獨立部署,分散流量,避免不合適的流量影響主體業(yè)務(wù)。

使用獨立域名,或者按照一定的URL規(guī)則在反向代理層進行路由。

做好系統(tǒng)保護和限流,進一步減少不必要的流量。

當“到達系統(tǒng)中的請求數(shù)”明顯大于“系統(tǒng)能夠處理的最大請求數(shù)”時,可以直接拒絕這些多余的請求,直接返回“秒殺”活動結(jié)束的信息。例如,活動開始時的商品庫存是100,目前庫存只剩50了,如果“每臺服務(wù)器待處理的請求數(shù)”已經(jīng)超過“商品總庫存數(shù)(100)”了,則可以直接終止掉多余的請求。

4)數(shù)據(jù)庫層流量控制
對于請求到數(shù)據(jù)中的流量,寫入的流量就是真正下單成功的流量,即需要扣減庫存的動作。有如下建議:

如果不是臨時的活動,則建議使用獨立的數(shù)據(jù)庫作為“秒殺”活動的數(shù)據(jù)庫。

將數(shù)據(jù)庫配置成讀寫分離。

嘗試去除行鎖。

對于數(shù)據(jù)庫行鎖的優(yōu)化,可以通過將商品進行拆分來實現(xiàn)——增加ID,如下圖所示。對于單一的“秒殺”活動這會得到顯著效果。
從流量分層控制方案可看出,瞬時流量就像被漏斗過濾了似的,應(yīng)盡量將數(shù)據(jù)和請求量一層一層地過濾掉。這種流量分層控制核心思想:在不同的層級中盡可能地過濾掉無效的請求,到達“倒三角”最末端的請求才是有效的請求。

5)高可用
在系統(tǒng)設(shè)計時想要做到高可用,避免單節(jié)點的一個小妙招:將服務(wù)無狀態(tài)化。如果無法完全無狀態(tài)化(如存儲系統(tǒng)),則可以通過冗余多個備份節(jié)點的方案來避免單節(jié)點。

由于篇幅原因,高可用此處就不再贅述,大家可以查看《高并發(fā)系統(tǒng)實戰(zhàn)派》一書里面針對高并發(fā)系統(tǒng)的真實設(shè)計案例,毫無保留的分享出了企業(yè)級高并發(fā)系統(tǒng)實戰(zhàn)。

  1. 扣減庫存設(shè)計
    由于在“秒殺”場景中商品一般優(yōu)惠力度很大,對用戶很具有吸引力,所以,在這種場景中使用“下單扣庫存”方式更為合適。

在“秒殺”場景中,大部分用戶抱著“搶到就是賺到”的想法,基本都會去付款的,但如果真有競爭對手惡意下單不付款,那我們該怎么辦?前面在流量管控中已經(jīng)說到,可以對請求日志進行實時分析,讓風(fēng)控系統(tǒng)選擇出惡意用戶,然后將其封停。

在“秒殺”場景中,通過流量分層控制可以分層管控大量的“讀”請求。但是,依然會有很大的流量進入真正的下單邏輯。對于這么大的流量,除前面說的數(shù)據(jù)庫隔離外,還需要進一步優(yōu)化庫存,否則數(shù)據(jù)庫讀/寫依然是系統(tǒng)的瓶頸。

接下來看看如何優(yōu)化大流量“秒殺”場景中的庫存數(shù)量扣減操作。
1)利用緩存技術(shù)
在“秒殺”場景中,如果只是一個扣減庫存數(shù)量這樣的簡單流程,則可以先將庫存數(shù)量直接放在緩存中,然后用分布式緩存(如Redis)的超高性能去應(yīng)對這種瞬時流量洪峰下的系統(tǒng)挑戰(zhàn)。

使用緩存是存在一定風(fēng)險的,比如,緩存節(jié)點出現(xiàn)了異常,那庫存數(shù)量該怎么算?

使用緩存,不僅要考慮分布式緩存高可用(如何設(shè)計可以查看我的新書“高并發(fā)系統(tǒng)實戰(zhàn)派”),還要考慮各種限流容錯機制,以確保分布式緩存對外提供服務(wù)。

2)異步處理技術(shù)
如果是復(fù)雜的扣減庫存(如涉及商品信息本身或牽連其他系統(tǒng)),則建議使用數(shù)據(jù)庫進行庫存數(shù)量的扣減,可以使用異步的方式來應(yīng)對這種高并發(fā)的庫存的更新。

①在用戶下單時,不立刻生成訂單,而是將所有訂單依次放入隊列。

②下單模塊依據(jù)自身的處理速度,從隊列中依次獲取訂單進行“下單扣庫存”操作。

③在訂單生成成功后,用戶即可進行支付操作了。

這種方式是針對“秒殺”場景的,依據(jù)“先到先得”原則來保證公平公正,所有用戶都可以搶購,然后等待訂單處理,最后生成訂單(如果庫存不足,則生成訂單失?。?。

這樣的邏輯,對用戶來說體驗不是很差。

那些技術(shù)

(1)數(shù)據(jù)的靜態(tài)化的技術(shù)
用來應(yīng)對高并發(fā)讀的請求,主要涉及以下內(nèi)容,這些在《高并發(fā)系統(tǒng)實戰(zhàn)派》一書中詳細分享了真實使用場景已經(jīng)技術(shù)方案:

各層級緩存的處理(即多級緩存的技術(shù))

分布式緩存技術(shù)

(2)負載均衡反向代理技術(shù)
LVS

Nginx

(3)異步處理技術(shù)
消息隊列技術(shù)

排隊系統(tǒng)技術(shù)

(4)系統(tǒng)架構(gòu)設(shè)計技術(shù)
系統(tǒng)模塊化劃分

微服務(wù)架構(gòu)思想

(5)系統(tǒng)監(jiān)控技術(shù)
日志監(jiān)控

服務(wù)監(jiān)控

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容