秒殺系統中的扣減庫存和流量削峯

 

前言

上篇文章我們一起討論了秒殺系統下,通過堆加機器解決高併發的方案有什麼缺點,又討論了使用多級緩存架構構建靜態化頁面,來減輕前端頁面服務器壓力的方式。

今天我們就接着往下討論,小夥伴們可以看一下上一篇文章做個複習,討論一下秒殺系統的技術難點與解決方案

我們先回顧一下場景。

假如我們的系統在00:00有一場秒殺活動,那麼會有大量用戶會提前幾分鐘開始刷新頁面,這部分的解決方案上篇文章已經提出。

緊接着就是到了00:00之後,頁面上可能會出現一個按鈕,大量用戶就會通過點擊按鈕開始向後臺發送請求,搶購商品。

搶購到之後還要有下訂單、支付、減庫存等後續一系列的流程,所以不對這些操作進行優化,直接操作數據庫,系統的壓力一定是很大的。

接下來我們就針對這個問題一起看看如何解決吧。

 

驗證用戶身份

首先我們思考一個問題,對於秒殺活動,會不會有人作弊呢?

比如寫好一段代碼,在秒殺活動開始之前就不停的循環刷新頁面,搶購商品。

王子告訴大家,這種情況是一定會發生的。其實我們看看各種搶票軟件就明白了,每次高峯期搶票不也會有很多的渠道去刷票嗎,這麼看來12306能支持這麼多的併發確實做得還不錯。

那麼如何針對這種作弊的行爲呢,其實我們可以在秒殺成功之後做一個驗證用戶身份的功能,保證你是人而不是代碼。

方式可以是彈出框做個驗證碼驗證,或者做個答題功能,需要人工答對之後才能進行下一步的操作。

這個辦法是非常有效的,不僅可以對作弊行爲進行過濾,而且每個人回答的速度是不一樣的,所以用戶發起的請求就不會全部的積壓在一個時間點上。

 

獨立的秒殺系統集羣

身份驗證過後,用戶就會把大量的請求發送到我們的訂單系統中,那麼問題來了,在秒殺活動中發起的海量請求,是要發給我們平時運行時使用的同一個訂單系統集羣中嗎?

我們來思考一個問題,假如秒殺業務和平時的業務使用的是一套訂單系統集羣,那麼在秒殺活動的時候,可能有海量的用戶來參加秒殺活動,但是同樣也有不會參加秒殺活動的用戶在同時訂購商品。

那麼當秒殺開始的時候,訂單服務器壓力會劇增,普通用戶也發起請求到訂單服務器,這樣會發生什麼呢?

很可能服務器由於秒殺系統帶來的壓力,性能變差,那麼普通用戶在進行正常的下訂單操作時也會發現系統運行緩慢。

所以我們要單獨部署一套秒殺系統集羣,單獨處理秒殺業務,從而不影響正常業務的性能。

而且單獨的秒殺系統集羣也更容易做一些特殊的架構優化,說到這裏,架構圖如下:

 

 

扣減庫存的優化

後臺系統在用戶搶購成功後,應該先做什麼操作呢?

第一步操作就是扣減庫存,因爲大家知道,參與秒殺活動的商品都是有數量限制的,所以大量用戶搶購成功後的第一步操作就是扣減庫存。

那麼如何進行扣減庫存的操作呢?

小夥伴們可能會回答,可以在秒殺系統集羣中調用庫存系統接口,連接數據庫,更新庫存數量。但這樣一來不就又面臨着數據庫壓力過大的問題了嗎?

其實我們可以在活動開始前,把要秒殺的商品庫存存放到Redis集羣中,然後扣減庫存的時候只操作Redis集羣,就可以大大降低數據庫壓力了。

當商品的庫存扣減完畢之後,用戶發送過來搶購的請求其實就不必再發送給秒殺系統了,可以直接在Nginx中過濾掉。

Nginx具體如何過濾呢?這裏王子提出一點思路,我們可以通過Zookeeper來實現。

當商品庫存爲0後,我們可以在Zookeeper中設置一個標誌,表名商品已經售空了,同時可以利用Zookeeper的監聽機制,告知Nginx的lua腳本,然後Lua腳本直接過濾掉無效的請求,並返回用戶一個“庫存已售空”的響應信息就可以了。

這樣可以很大幅度的減少海量請求對後臺秒殺系統的壓力。

 

引入RocketMQ進行流量削峯

通過之前的優化,已經過濾掉了大量的無用請求,那麼針對正常參加秒殺,發送給後臺的請求我們應該怎麼進行架構優化呢?

這個時候我們就可以引入RocketMQ,來進行流量削峯了

也就是說,當用戶發送請求,經過Redis扣減庫存的操作後發現庫存數量還是大於0的,那麼這個時候就可以把創建訂單的操作發送消息給RocketMQ,然後我們平時使用的訂單系統從RocketMQ中限流獲取消息,進行常規的操作(生成訂單、支付等等)。這樣就不會對數據庫有太大的壓力了。

由於訂單系統限流獲取消息,所以會造成RockeMQ的消息積壓問題,但RocketMQ是高可用的集羣,可以保證消息的不丟失。所以完全可以讓訂單系統每秒幾千條的速度去消費,頂多可能會延遲個幾十秒纔會生成訂單而已。

所以我們最後的架構圖如下:

 

總結

到這裏,相信小夥伴們對於秒殺系統的架構方案已經有了一個整體的瞭解了。

其實總結起來,秒殺系統的架構優化核心就是:單獨部署抗下高併發的服務器集羣,阻止高併發請求訪問數據庫

因爲數據庫是整個系統架構中的性能瓶頸,不可能無限擴展數據庫服務器的數量來抗下高併發請求。而且不是所有時候系統都有這麼高的併發的,擴展數據庫並不划算。

還有在這裏王子要說明一點,一套完整的秒殺系統架構體系是很複雜的,我們只是通過這麼一個秒殺業務的場景,讓小夥伴們感受到消息中間件在這樣的架構中扮演的角色。

後續的文章裏,我們還會一起深入的探討消息中間件的底層原理,讓我們一起進步吧。

 

 

往期文章推薦:

中間件專輯:

什麼是消息中間件?主要作用是什麼?

常見的消息中間件有哪些?你們是怎麼進行技術選型的?

你懂RocketMQ 的架構原理嗎?

聊一聊RocketMQ的註冊中心NameServer

Broker的主從架構是怎麼實現的?

RocketMQ生產部署架構如何設計

RabbitMQ和Kafka的高可用集羣原理

RocketMQ的發送模式和消費模式

討論一下秒殺系統的技術難點與解決方案

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章