秒殺系統設計中的業務性思考

ForestXie發表於2019-03-03

    秒殺不是一個新鮮事物,特別是過去幾年電商和互金業務的蓬勃發展,各種電商節的興起,促使秒殺已經變成了非常重要的業務功能。我這幾年也沒少和“秒殺”打交道,和團隊共同經歷了各種掙扎後,積累了一些想法,今天想利用這個機會來寫一寫。但今天不是來教大家如何做一個秒殺系統的,而是從業務的角度來思考秒殺系統設計中,我們需要注意的地方。


業務對於秒殺的期望


既然我們要從業務的思路上來思考秒殺,那麼我們就需要明確和轉化,在秒殺場景下,我們期待的結果是什麼。拋開具體業務,我簡單總結了一下,可以分為以下兩點:



1)每個使用者都能參與,但是有且參與一次。

2)參與的使用者都是真實有效的。

針對這兩個業務需求,我再來分析一下,要滿足這兩個業務需求,我們的秒殺系統需要具備什麼能力。

先說第1點,用技術的語言來翻譯就是:同一個賬戶,無論通過瀏覽器外掛或者其他任何輔助工具發出多次請求,他最多隻能搶到一次。講到這裡,我必須要多說兩句,這看似是一個簡單的判斷領取邏輯,但是不少團隊在這裡是犯過錯誤的,導致判斷邏輯被繞過,沒有達到去重的效果,如下圖:

秒殺系統設計中的業務性思考


先判斷使用者A是否有參與記錄,如果沒有則領取成功,最後將使用者A更新為已參與記錄中。如果大家仔細想一下,就會發現這裡藏著一個極大的漏洞:在高併發的場景下,在某個請求成功寫入參與記錄的時間段內,使用者A其他的請求獲查詢到的結果都是“沒有參與記錄”。所以,就存在邏輯判斷被繞過,同一個使用者秒殺成功多次的情況出現。


正確的做法:


秒殺系統只允許接受同一個賬戶的1個請求,其他請求統統過濾掉。在程式入口加鎖,同一個賬戶,同一時刻只有一個執行緒在被處理。不僅解決了同一個賬號,傳送多個請求的問題,還保證了後續的邏輯流程的安全,確保了只有一個執行緒能更新賬戶的狀態。


第1個問題解決後,接下來,我們需要談一下,怎麼保證秒殺過程中,使用者的真實性和有效性。

要總結出真實使用者的行為是比較難的,但是要總結出非真實使用者的行為相對容易,所以我們採用反證法的思路,將問題2進行一個拆解,列舉出非真實使用者行為的表現有哪一些:



  1. IP相對固定(相近IP或者同一IP段),請求的頻率超過正常人的反應速度

  2. 請求的路徑缺乏邏輯,不能形成正常的業務鏈路。

  3. User-Agent異常,URL攜帶的引數存在明顯的拼接痕跡。


針對以上幾點非正常情況,我們可以有以下兩種防範措施:


1. 對請求頻率過快的IP進行限制。 可以在Nginx或者Tengine上執行,詳細資訊,可以參見之前我有關服務端限流的文章

2. 頻率請求過快或者請求頭異常的請求,返回圖形驗證碼到前端(建議不要使用簡單的數字驗證碼),觸發人工解鎖,確保背後是真實的人存在。


進一步思考


實際上,光靠這些技術手段還是不夠的,因為羊毛黨或者黃牛黨是在不斷進化手段的,人家也肯下血本。所以我們真要做好秒殺,還需要更多從業務上思考。我在這裡也總結了2點,可以嘗試:


  1. 分析使用者畫像,根據使用者的活躍度,等級,資料的齊全程度,歷史購買產品,對使用者進行評分,達到特定分數的使用者才能參與秒殺。

  2. 制定業務門檻,比如說,要參與秒殺,對於一個電商平臺,該使用者過去至少有1000元的歷史消費額,對於一個理財平臺,該使用者必須要有訂單在投,等等。


有了這2點,可以說基本上保證了使用者的真實性,或者說讓造假的動機沒了,保證99%以上的黃牛號或者殭屍號能被過濾掉。


選擇“秒殺券”還是“秒殺商品”


最後,再想討論一個話題,如果要做一個秒殺系統,是先從秒殺券做起,還是從秒殺商品開始做起呢?個人建議先通過秒殺券練練手,然後再轉向秒殺商品。原因很簡單,因為秒殺商品,一下就引入了訂單和支付,庫存的鎖定和釋放,支付的時效等等,涉及到的業務複雜度就高了一個層次。從另外一個角度看,秒殺券是和正常的業務流程隔離的,是不會影響到正常的下單流程的。即便是出問題了,做服務降級也會容易許多。


預告一下:明天會講一下商品秒殺系統的落地方案,歡迎圍觀。



掃描二維碼或手動搜尋微信公眾號【架構棧】: ForestNotes

歡迎轉載,帶上以下二維碼即可

秒殺系統設計中的業務性思考




相關文章