博客 / 詳情

返回

搞定秒殺,只需要這幾步!!

靈魂拷問
  • 秒殺這種大併發的寫場景,直接分庫分表開幹?
  • 應對秒殺活動的流量高峯很難嗎?
  • 不要拿淘寶級別的秒殺忽悠我

秒殺活動特點

我敢説凡是做過電商的同學,都會遇到運營展開的秒殺,限時購等“高併發”的活動。市面上也有不少針對秒殺的解決方案,什麼分庫分表,緩存,消息隊列呀,但凡能想到的技術“靚點”都基本會寫上一段。我覺得應對秒殺這樣的帶有流量峯值的業務,還是要仔細分析業務的特性,以及根據自己系統的業務量來確定需要採用哪些技術“靚點”,假如:一個日活10萬的系統,採用了分庫分表,緩存,消息隊列,限流,降級等等技術手段,雖然功能上達到了預期,但是其實資源上可能會有些浪費,技術上也許只需要一個限流手段就足夠了。説這些不是想表達什麼,我只是想説,那些上來就分庫分表等“大手筆”的“優化”手段一定要根據實際業務去考察是否需要實施。

言歸正傳,秒殺這種業務場景其實特點很明顯:

  • 帶有短期流量峯值特性,即:短時間內會有大量的請求涌入
  • 請求的數據帶有熱點性,即:大量的請求同一數據
  • 請求的成功有效率低,即:大量的請求中可能只有少量請求會成功處理業務
  • 請求的流量峯值發生在下單之前,即:付款階段很少存在流量峯值

靜態資源

靜態資源是指商品的圖片,視頻,音頻,html頁面等幾乎不會變化的資源,這些資源的處理方式和緩存類似,儘量放在離用户最近的地方,比如:瀏覽器的本地緩存,當緩存過期的時候,優先推薦從CDN中獲取,CDN是應對靜態資源訪問高峯的最簡單粗暴,也是最有效的解決方案,如果沒有CDN怎麼辦?那最少要把請求這些靜態資源的服務器和後台業務服務器物理上分離,避免因為靜態資源而影響正常的業務。比如:很早之前,我就喜歡每個項目單獨一個存放圖片,css,js的網站,這個網站的優勢是無狀態,可以做到傻瓜式橫向擴展。

至於靜態資源的緩存更新,我想你可以百度一下會有很多答案。

業務讓步

如果負責秒殺活動的產品經理是一個優秀的產品經理的話,就不會設計出:用户點擊秒殺馬上給予是否下單成功,這樣的系統。熟悉分佈式的同學肯定會想到,想保證這樣的數據一致性,在可用性上必然會有所犧牲。尤其是秒殺這樣的業務,我覺得可用性要比一致性優先級要高,所以幾乎所有的秒殺系統都會採用BASE理論來設計系統,一致性上採用最終一致性。在用户看來,點擊秒殺按鈕之後會彈出一個等待的提示,在技術上我們稱之為:異步處理。異步處理對於用户最明顯的感知就是不會馬上得到結果,而是要等待一段時間。其實這樣的設計也是在技術和業務之間的一個權衡,算是業務作出的讓步。

至於秒殺之前需要輸入驗證碼或者某些題的答案等手段,其實也可以算是業務上作出的一些讓步。為什麼説是讓步呢?對於用户來説,最理想的秒殺場景是:一點秒殺按鈕,馬上給予結果,但是技術上難度太大了,所以嘛,互相讓一步,大家都好過,對不對?

技術第一招:限流

對於秒殺出現的流量峯值,限流是最直接的削峯手段,被限制的請求可以直接返回,客户端提示請求中提示。可想而知,當10000/S的請求量被削成100/S的量,估計系統稍微優化一下就能抗住,至於限流的策略根據業務會有很多不同的方式,比如:

  • 針對同一個用户的請求次數限流,例如:每個用户每10秒只允許請求一次
  • 針對同一個IP的請求次數限流,例如:每個IP每10秒只允許請求一次

至於限流的算法,之前寫過一篇文章來介紹,而且性能還不錯哦

高併發優雅的做限流

第二招:消息隊列

説到消息隊列,每個程序員都不陌生,它相當於一個快速的數據容器,可以作為一個緩衝層來應對流量高峯。如果從它的使用場景上來看,它可以算是低速設備和高速設備之間的平衡者,使用消息隊列來進行削峯是一個很明顯的異步流程。

應用到秒殺的場景下,大量的請求會先進入消息隊列,它不僅削平了流量的峯值,而且把秒殺下單的這個流程異步化,只要把請求都暫存入隊列,消費端慢慢消費即可,但是這裏要注意,如果消費的速度遠遠慢於消息的投遞速度,可能會影響整個系統性能。

除了削峯之外,我始終認為消息隊列的最大作用是系統解耦,它把下單和支付解耦,下單和支付業務可以隨着自身系統的承載量來單獨擴容。

第三招:緩存

為什麼要加入緩存這個選項呢?別忘了,除了大量的用户下單這個寫操作之外,還有更大量的用户請求下單結果這個讀操作。當用户點擊秒殺按鈕之後,系統會彈出等待的提示框,很多系統是不停的去輪訓用户的下單結果,我之前也寫過緩存的文章,曾經提到過緩存最大的作用是提供讀操作的快速響應。整個秒殺系統可以這樣做:

  • 用户點擊下單按鈕,請求經過限流組件,如果成功,則進入下單環節(這裏可以進入消息隊列,異步下單)
  • 服務端無論是採用redis緩存,還是其他緩存組件,存放着下單成功的用户信息(也可以包括訂單信息)
  • 客户端採用輪訓的方式去查詢緩存,如果查詢到信息説明下單成功,進入支付環節,未查詢到則説明下單還未成功
  • 服務端下單成功,往緩存中寫入數據,當用户下次再次查詢的時候會提示下單成功。

雖然過程很簡單,但是其實整個過程中有很多細節需要注意,比如:緩存的過期時間怎麼設置?能否引入下單中的狀態?怎麼保證緩存數據和數據庫數據的一致性?

談了千百遍的緩存數據的一致性問題

除了以上的信息數據緩存,商品的信息數據也可以放在緩存中,由於讀的請求量比較大,可以考慮採用緩存副本的方式來提高整體的吞吐量。

寫在最後

其實很多系統應用上消息隊列+限流之後,針對秒殺業務已經足夠了,其餘的分庫分表等方案可以根據自己的業務量來確定。每個系統在滿足功能性的需求下,也在滿足非功能性需求的前提下越簡單越好,不是每個系統都需要淘寶的架構。

更多精彩文章

  • 分佈式大併發系列
  • 架構設計系列
  • 趣學算法和數據結構系列
  • 設計模式系列

image

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.