B2C電商項目 秒殺業務 工作總結

秒殺前端業務

秒殺商品通常有兩種限制:庫存限制、時間限制。

1)秒殺頻道首頁列出秒殺商品
(4)點擊立即搶購實現秒殺下單,下單時扣減庫存。當庫存爲0或不在活動期範圍內時無法秒殺。
(5)秒殺下單成功,直接跳轉到支付頁面(微信掃碼),支付成功,跳轉到成功頁,填寫收貨地址、電話、
收件人等信息,完成訂單。
(6)當用戶秒殺下單5分鐘內未支付,取消預訂單,調用微信支付的關閉訂單接口,恢復庫存。

在這裏插入圖片描述
緩存數據加載思路:定義定時任務,每天凌晨會進行當天所有時間段秒殺商品預加載。並且在B端進行
限制,添加秒殺商品的話,只能添加當前日期+1的時間限制,比如說:當前日期爲8月5日,則添加秒殺
商品時,開始時間必須爲6日的某一個時間段,否則不能添加。

當前業務整體流程分析

1.查詢所有符合條件的秒殺商品
1) 獲取時間段集合並循環遍歷出每一個時間段
2) 獲取每一個時間段名稱,用於後續redis中key的設置
3) 狀態必須爲審覈通過 status=1
4) 商品庫存個數>0
5) 秒殺商品開始時間>=當前時間段
6) 秒殺商品結束<當前時間段+2小時
7) 排除之前已經加載到Redis緩存中的商品數據
8) 執行查詢獲取對應的結果集
2.將秒殺商品存入緩存

前臺

1)加載時間菜單
2)加載時間菜單下秒殺商品信息

加載時間菜單分析

每2個小時就會切換一次搶購活動,所以商品發佈的時候,我們將時間定格在2小時內搶購,每次發佈商
品的時候,商品搶購開始時間和結束時間是這2小時的邊界。
每2小時會有一批商品參與搶購,所以我們可以將24小時切分爲12個菜單,每個菜單都是個2小時的時
間段,當前選中的時間菜單需要根據當前時間判斷,判斷當前時間屬於哪個秒殺時間段,然後將該時間
段作爲選中的第1個時間菜單。

加載對應秒殺商品分析

進入首頁時,到後臺查詢時間菜單信息,然後將第1個菜單的時間段作爲key,在Redis中查詢秒殺商品
集合,並顯示到頁面,頁面每次點擊切換不同時間段菜單的時候,都將時間段傳入到後臺,後臺根據時
間段獲取對應的秒殺商品集合。

時間菜單實現

時間菜單顯示,先運算出每2小時一個搶購,就需要實現12個菜單,可以先計算出每個時間的臨界值,
然後根據當前時間判斷需要顯示12個時間段菜單中的哪個菜單,再在該時間菜單的基礎之上往後挪4個
菜單,一直顯示5個時間菜單。

倒計時實現

基礎數據顯示
定義一個集合,用於存放五個時間段的倒計時時間差,集合中每一個角標都對應一個倒計時時間差,比
如:集合角標爲0,對應第一個倒計時時間差。集合角標爲1,對應第二個倒計時時間差,依次類推。
因爲要有倒計時的效果,所以後續會遍歷該時間集合,並讓集合中的每一個時間循環遞減即可

加載秒殺商品實現

當前已經完成了秒殺時間段菜單的顯示,那麼當用戶在切換不同的時間段的時候,需要按照用戶所選擇
的時間去顯示相對應時間段下的秒殺商品

秒殺後端

秒殺異步下單
用戶在下單的時候,需要基於JWT令牌信息進行登陸人信息認證,確定當前訂單是屬於誰的。
針對秒殺的特殊業務場景,僅僅依靠對象緩存或者頁面靜態化等技術去解決服務端壓力還是遠遠不夠。
對於數據庫壓力還是很大,所以需要異步下單,異步是最好的解決辦法,但會帶來一些額外的程序上的
複雜性。

當預加載秒殺商品的時候,提前加載每一個商品的庫存信息,後續減庫存操作也會先預扣減緩存中的庫
存再異步扣減mysql數據。
預扣減庫存會基於redis原子性操作實現

秒殺下單業務層實現
業務邏輯:
獲取秒殺商品數據與庫存量數據,如果沒有庫存則拋出異常
執行redis預扣減庫存,並獲取扣減之後的庫存值
如果扣減完的庫存值<=0, 則刪除redis中對應的商品信息與庫存信息
基於mq異步方式完成與mysql數據同步(最終一致性)

注意:庫存數據從 redis中取出,轉換成String

生產者保證消息不丟失
在這裏插入圖片描述
按照現有 rabbitMQ的相關知識,生產者會發送消息到達消息服務器。但是在實際生產環境下,消息生
產者發送的消息很有可能當到達了消息服務器之後,由於消息服務器的問題導致消息丟失,如宕機。因
爲消息服務器默認會將消息存儲在內存中。一旦消息服務器宕機,則消息會產生丟失。因此要保證生產
者的消息不丟失,要開始持久化策略。

rabbitMQ持久化:
交換機持久化
隊列持久化
消息持久化

但是如果僅僅只是開啓這兩部分的持久化,也很有可能造成消息丟失。因爲消息服務器很有可能在持久
化的過程中出現宕機。因此需要通過數據保護機制來保證消息一定會成功進行持久化,否則將一直進行
消息發送。

RabbitMQ數據保護機制
事務機制
 事務機制採用類數據庫的事務機制進行數據保護,當消息到達消息服務器,首先會開啓一個事務,接着進
行數據磁盤持久化,只有持久化成功纔會進行事務提交,向消息生產者返回成功通知,消息生產者一旦接收成
功通知則不會再發送此條消息。當出現異常,則返回失敗通知.消息生產者一旦接收失敗通知,則繼續發送該
條消息。
 事務機制雖然能夠保證數據安全,但是此機制採用的是同步機制,會產生系統間消息阻塞,影響整個系統
的消息吞吐量。從而導致整個系統的性能下降,因此不建議使用。
confirm機制
 confirm模式需要基於channel進行設置, 一旦某條消息被投遞到隊列之後,消息隊列就會發送一個確
認信息給生產者,如果隊列與消息是可持久化的, 那麼確認消息會等到消息成功寫入到磁盤之後發出.
confirm的性能高,主要得益於它是異步的.生產者在將第一條消息發出之後等待確認消息的同時也可以
繼續發送後續的消息.當確認消息到達之後,就可以通過回調方法處理這條確認消息. 如果MQ服務宕機了,則會
返回nack消息. 生產者同樣在回調方法中進行後續處理

消費者手動ACK下單實現
按照現有RabbitMQ知識,可以得知當消息消費者成功接收到消息後,會進行消費並自動通知消息服務
器將該條消息刪除。此種方式的實現使用的是消費者自動應答機制。但是此種方式非常的不安全。
在生產環境下,當消息消費者接收到消息,很有可能在處理消息的過程中出現意外情況從而導致消息丟
失,因爲如果使用自動應答機制是非常不安全。
我們需要確保消費者當把消息成功處理完成之後,消息服務器纔會將該條消息刪除。此時要實現這種效
果的話,就需要將自動應答轉換爲手動應答,只有在消息消費者將消息處理完,纔會通知消息服務器將該
條消息刪除。

更改配置文件 將自動應答轉換爲手動應答

rabbitmq:
 host: 192.168.200.128
 listener:
  simple:
   acknowledge-mode: manual #手動

流量削峯
在秒殺這種高併發的場景下,每秒都有可能產生幾萬甚至十幾萬條消息,如果沒有對消息處理量進行任
何限制的話,很有可能因爲過多的消息堆積從而導致消費者宕機的情況。因此官網建議對每一個消息消
費者都設置處理消息總數(消息抓取總數)。
消息抓取總數的值,設置過大或者過小都不好,過小的話,會導致整個系統消息吞吐能力下降,造成性
能浪費。過大的話,則很有可能導致消息過多,導致整個系統OOM。因此官網建議每一個消費者將該
值設置在100-300之間。
1)更新消費者。

//設置預抓取總數
channel.basicQos(300);

防止惡意刷單解決
在生產場景下,很有可能會存在某些用戶惡意刷單的情況出現。這樣的操作對於系統而言,會導致業務
出錯、髒數據、後端訪問壓力大等問題的出現。
一般要解決這個問題的話,需要前端進行控制,同時後端也需要進行控制。後端實現可以通過Redis
incrde 原子性遞增來進行解決。

秒殺下單接口隱藏
當前雖然可以確保用戶只有在登錄的情況下才可以進行秒殺下單,但是無法方法有一些惡意的用戶在登
錄了之後,猜測秒殺下單的接口地址進行惡意刷單。所以需要對秒殺接口地址進行隱藏。
在用戶每一次點擊搶購的時候,都首先去生成一個隨機數並存入redis,接着用戶攜帶着這個隨機數去訪
問秒殺下單,下單接口首先會從redis中獲取該隨機數進行匹配,如果匹配成功,則進行後續下單操作,
如果匹配不成功,則認定爲非法訪問。

秒殺下單接口限流
因爲秒殺的特殊業務場景,生產場景下,還有可能要對秒殺下單接口進行訪問流量控制,防止過多的請
求進入到後端服務器。對於限流的實現方式,我們之前已經接觸過通過nginx限流,網關限流。但是他
們都是對一個大的服務進行訪問限流,如果現在只是要對某一個服務中的接口方法進行限流呢?這裏推
薦使用google提供的guava工具包中的RateLimiter進行實現,其內部是基於令牌桶算法進行限流計算

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