本文是新系列「實戰高併發」的開篇做。這個系列做爲「我說分佈式」的子系列,將着重挑選若干典型的分佈式實戰場景,儘可能對當下高併發領域較爲熱門的架構及業務場景作一次較爲深刻的實踐與總結。前端
該系列既是對筆者接觸過的業務的整理,也但願系列中分享的套路可以對讀者朋友解決實際業務中面臨的問題有所幫助。git
言歸正傳,本文我將主要從業務場景及技術架構等方面出發,對」電商高併發秒殺」這一業務場景作一次較爲全面的闡述,同時做爲後續實操的開發設計依據。github
「秒殺」這一業務場景在現在已經不是什麼新鮮名詞,它本質上屬於短時突發性高併發訪問問題,業務特色以下:面試
分析一下這些秒殺場景的典型特色,咱們不難看出,秒殺場景屬於典型的高併發場景,對系統的衝擊較大。咱們來對上述特色進行逐一分析:後端
這不難理解,秒殺活動每每伴隨着固定的節日、活動而開展,在某一個肯定時間對C端用戶開放訪問能力,此時每每會出現一個較爲明顯的請求激增。如:每一年「雙11」當天0點,淘寶等電商平臺訪問量基本上會出現明顯的請求波峯,這與秒殺的定時性,息息相關。緩存
這是確定的,在庫存有限、請求接收較多的狀況下,常會存在部分請求處理成功,部分請求處理失敗的狀況。性能優化
若是庫存是無限的,也就不存在秒殺這一說了。也正是由於庫存有限,平臺以此爲賣點,採起定時限量售賣的營銷策略更能刺激用戶進行訪問。架構
通常狀況,秒殺場景下的商品售價較平時都有明顯的優惠。併發
商品數量有限在上文已經說過了,咱們聊聊「超賣」、「少賣」的問題。異步
超賣是不能容忍的狀況,若是發生超賣,則屬於業務異常了。通常狀況下商家只會提供有限數量的商品做爲秒殺營銷商品,若是超賣,則商家每每面臨較爲明顯的虧損。這在業務上是不能出現的。
少賣則是可以接受的,好比商家提供了10臺IPhoneX做爲秒殺庫存,因爲臨時減庫存或其餘緣由(每每都是業務上的緣由)調整隻賣了9臺。這對商家而言並無多大的損失,商家還能夠以更高的價格去售賣該多餘庫存,並且平臺由於該秒殺活動還收穫了較高的PV/UV,整體而言是沒有損失的。
所以咱們在設計秒殺架構的時候要以 「超賣零容忍,少賣能兼容」 這一設計原則進行設計。
因爲秒殺業務的特殊性–短時超高併發,所以咱們不能按照傳統的交易場景進行設計。
傳統交易場景下,對於用戶的下單請求通常都是同步處理,即同步落庫持久化,並同步返回收單結果。
若是咱們對秒殺訂單採用同步持久化的作法,則系統的吞吐量將基本依賴DB的性能,這在成本上、性能上都有較大壓力。所以,咱們要在儘可能提升系統收單入口吞吐量的同時下降系統開發部署的成本。
「不要求當即返回真實下單結果」,也就是不須要當即持久化,換言之也就是業務流程 「異步化」 。
明確了流程能夠異步化,解決的手段就多了。利用緩存、隊列、線程池都能實現業務的異步化。這裏也反映出
技術是圍繞業務運轉的,沒有業務做爲支撐,不管技術多麼新穎、其性能多麼高,它都無用武之地。
經過對秒殺核心業務流程進行異步化,咱們可以將主流程分爲收單、下單兩個階段,業務流程歸納起來以下:
到此,對用戶側的交互就告一段落。
下單流程中,平臺的壓力經過中間層的緩衝其實已經小了不少,之因此會少,一方面是由於在用戶下單的同步校驗過程當中就過濾掉了部分非法請求;另外一方面,咱們經過在中間層作一些限流、過濾等邏輯對下單請求作限速、壓單等操做,將下單請求在內部慢慢消化,儘量減小流量對平臺持久層的衝擊。這裏其實就體現了中間層 「削峯填谷」 的特色。
基於上述前提,咱們簡單總結下秒殺下單部分的業務邏輯。
到此,基本上就是秒殺業務的核心主流程。
進一步抽象 秒殺請求->中間層->真實下單 這個場景,是否是很像咱們常常用到的一種異步業務處理模式?
相信有心的你已經看出來了,沒錯,這就是 「生產者-消費者」 模式。
「生產者-消費者」模式 在進程內,經常經過 阻塞隊列 或者 「等待-通知」 等機制實現,在服務之間則每每經過消息隊列實現,這也是本次實戰所採用的技術實現手段。在後續的實戰中,我將經過RocketMQ消息隊列,對秒殺下單進行解耦,實現削峯填谷、提升系統吞吐量的目的。此處就很少贅述,到編碼部分再詳細展開。
看了這麼多文字,可能讀者朋友仍是有不清楚的地方,那麼咱們就經過圖解的方式來對流程進行更加直觀的理解。
詳細細節在上文中的描述部分已經作過闡述,讀者朋友能夠配合一塊兒看,這裏只對圖示流程進行簡略總結:
1:用戶訪問秒殺網關seckill-gateway-service,對感興趣的商品發起秒殺操做。特別的,對於商品信息,在系統初始化的時候已經加載到seckill-gateway-service。在進行前置庫存校驗的時候,依據緩存已經作了一次用戶下單流量的過濾。
2:網關對秒殺訂單進行充分的預校驗以後,將秒殺下單消息投遞到RocketMQ中,同步向用戶返回排隊中
3:秒殺訂單平臺seckill-order-service訂閱秒殺下單消息,對消息進行冪等處理,並對商品庫存進行真實校驗後,進行真實下單操做
咱們本次實戰主要關注 收單、下單 這兩個核心場景,對於後續的支付及通知不作涉及,更多的關於下單通知場景,在後面的實戰系列會逐步的進行呈現。
本流程爲用戶經過秒殺網關seckill-gateway-service提供的查單接口對本身下的秒殺訂單進行查詢跟蹤。
本文爲「實戰分佈式之電商高併發秒殺」的首篇,主要介紹了秒殺的業務特色及實現的思路,經過圖文配合的方式對 「秒殺」 這一高併發典型場景作了較爲全面的闡述。
因爲咱們的重點在於秒殺的核心場景,所以仍是存在有待優化的細節。此處一併羅列一下,做爲後續參考:
1:推薦採用分佈式減庫存策略:如:使用Redis的decr進行原子減庫存。
2:預熱庫存時,將庫存適當調大,防止惡意刷庫存致使正經常使用戶不能進行秒殺下單請求。這裏要注意只調整緩存中的庫存,不能調整商品庫中的真實庫存,不然會出現 「超賣」 從而致使損失。
3:秒殺接口須要作防刷處理,能夠在前端頁面經過倒計時方式定時開放接口;經過增長驗證碼減小下單頻率;經過增長下單前收貨地址校驗、實名認證等方式對殭屍用戶進行攔截。
PS:本次實戰主要從後端實現部分出發進行設計,所以對於前端部分的設計與注意點只作簡單概述,恕不展開。
項目完整源碼地址:
在此我向你們推薦一個架構學習交流羣。交流學習羣號:833145934 裏面資深架構師會分享一些整理好的錄製視頻錄像和BATJ面試題:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構等這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多。