前言
上篇文章我們一起討論了秒殺系統下,通過堆加機器解決高並發的方案有什么缺點,又討論了使用多級緩存架構構建靜態化頁面,來減輕前端頁面服務器壓力的方式。
今天我們就接着往下討論,小伙伴們可以看一下上一篇文章做個復習,討論一下秒殺系統的技術難點與解決方案
我們先回顧一下場景。
假如我們的系統在00:00有一場秒殺活動,那么會有大量用戶會提前幾分鍾開始刷新頁面,這部分的解決方案上篇文章已經提出。
緊接着就是到了00:00之后,頁面上可能會出現一個按鈕,大量用戶就會通過點擊按鈕開始向后台發送請求,搶購商品。
搶購到之后還要有下訂單、支付、減庫存等后續一系列的流程,所以不對這些操作進行優化,直接操作數據庫,系統的壓力一定是很大的。
接下來我們就針對這個問題一起看看如何解決吧。
驗證用戶身份
首先我們思考一個問題,對於秒殺活動,會不會有人作弊呢?
比如寫好一段代碼,在秒殺活動開始之前就不停的循環刷新頁面,搶購商品。
王子告訴大家,這種情況是一定會發生的。其實我們看看各種搶票軟件就明白了,每次高峰期搶票不也會有很多的渠道去刷票嗎,這么看來12306能支持這么多的並發確實做得還不錯。
那么如何針對這種作弊的行為呢,其實我們可以在秒殺成功之后做一個驗證用戶身份的功能,保證你是人而不是代碼。
方式可以是彈出框做個驗證碼驗證,或者做個答題功能,需要人工答對之后才能進行下一步的操作。
這個辦法是非常有效的,不僅可以對作弊行為進行過濾,而且每個人回答的速度是不一樣的,所以用戶發起的請求就不會全部的積壓在一個時間點上。
獨立的秒殺系統集群
身份驗證過后,用戶就會把大量的請求發送到我們的訂單系統中,那么問題來了,在秒殺活動中發起的海量請求,是要發給我們平時運行時使用的同一個訂單系統集群中嗎?
我們來思考一個問題,假如秒殺業務和平時的業務使用的是一套訂單系統集群,那么在秒殺活動的時候,可能有海量的用戶來參加秒殺活動,但是同樣也有不會參加秒殺活動的用戶在同時訂購商品。
那么當秒殺開始的時候,訂單服務器壓力會劇增,普通用戶也發起請求到訂單服務器,這樣會發生什么呢?
很可能服務器由於秒殺系統帶來的壓力,性能變差,那么普通用戶在進行正常的下訂單操作時也會發現系統運行緩慢。
所以我們要單獨部署一套秒殺系統集群,單獨處理秒殺業務,從而不影響正常業務的性能。
而且單獨的秒殺系統集群也更容易做一些特殊的架構優化,說到這里,架構圖如下:
扣減庫存的優化
后台系統在用戶搶購成功后,應該先做什么操作呢?
第一步操作就是扣減庫存,因為大家知道,參與秒殺活動的商品都是有數量限制的,所以大量用戶搶購成功后的第一步操作就是扣減庫存。
那么如何進行扣減庫存的操作呢?
小伙伴們可能會回答,可以在秒殺系統集群中調用庫存系統接口,連接數據庫,更新庫存數量。但這樣一來不就又面臨着數據庫壓力過大的問題了嗎?
其實我們可以在活動開始前,把要秒殺的商品庫存存放到Redis集群中,然后扣減庫存的時候只操作Redis集群,就可以大大降低數據庫壓力了。
當商品的庫存扣減完畢之后,用戶發送過來搶購的請求其實就不必再發送給秒殺系統了,可以直接在Nginx中過濾掉。
Nginx具體如何過濾呢?這里王子提出一點思路,我們可以通過Zookeeper來實現。
當商品庫存為0后,我們可以在Zookeeper中設置一個標志,表名商品已經售空了,同時可以利用Zookeeper的監聽機制,告知Nginx的lua腳本,然后Lua腳本直接過濾掉無效的請求,並返回用戶一個“庫存已售空”的響應信息就可以了。
這樣可以很大幅度的減少海量請求對后台秒殺系統的壓力。
引入RocketMQ進行流量削峰
通過之前的優化,已經過濾掉了大量的無用請求,那么針對正常參加秒殺,發送給后台的請求我們應該怎么進行架構優化呢?
這個時候我們就可以引入RocketMQ,來進行流量削峰了。
也就是說,當用戶發送請求,經過Redis扣減庫存的操作后發現庫存數量還是大於0的,那么這個時候就可以把創建訂單的操作發送消息給RocketMQ,然后我們平時使用的訂單系統從RocketMQ中限流獲取消息,進行常規的操作(生成訂單、支付等等)。這樣就不會對數據庫有太大的壓力了。
由於訂單系統限流獲取消息,所以會造成RockeMQ的消息積壓問題,但RocketMQ是高可用的集群,可以保證消息的不丟失。所以完全可以讓訂單系統每秒幾千條的速度去消費,頂多可能會延遲個幾十秒才會生成訂單而已。
所以我們最后的架構圖如下:
總結
到這里,相信小伙伴們對於秒殺系統的架構方案已經有了一個整體的了解了。
其實總結起來,秒殺系統的架構優化核心就是:單獨部署抗下高並發的服務器集群,阻止高並發請求訪問數據庫。
因為數據庫是整個系統架構中的性能瓶頸,不可能無限擴展數據庫服務器的數量來抗下高並發請求。而且不是所有時候系統都有這么高的並發的,擴展數據庫並不划算。
還有在這里王子要說明一點,一套完整的秒殺系統架構體系是很復雜的,我們只是通過這么一個秒殺業務的場景,讓小伙伴們感受到消息中間件在這樣的架構中扮演的角色。
后續的文章里,我們還會一起深入的探討消息中間件的底層原理,讓我們一起進步吧。
往期文章推薦:
中間件專輯: