秒殺架構優化,掌握這一個核心原則!
秒殺系統為什么難做?
根本原因,是庫存訪問集中在一個地方,所有請求會在集中的時間讀寫庫存數據,導致系統鎖死。
比如說:華為搶手機,可能庫存只有5K部,但瞬時進入的流量可能是十萬百萬。
又比如說,12306搶票,余票很少,瞬時流量會更高。
怎么優化?
最核心的優化思路是:盡量將請求攔截在系統的上游,而不要壓到庫存數據。
怎么攔截?
常見的分層架構如上,從上到下逐層攔截。
首先,端上攔截。
- 產品層面:用戶點擊“查詢”或者“搶購”后,按鈕置灰,禁止用戶重復提交請求。
- 技術層面:前APP端,或者H5端,限制同一個用戶在10秒之內只能向服務端提交一次請求,重復的請求前端直接返回。
如此限流,可攔截不少流量。
有人要說了,這個可行嗎?端上攔截,只能攔住小白用戶,大部分流量都是程序員抓包寫腳本,for循環,直接調用后端的HTTP接口訪問,那怎么辦?
第二步,web-server站點層攔截。
秒殺類的電商場景,用戶需要登錄,登錄就有token,有uid的唯一標識。
在站點層,同一個uid,做限速,限制同一個用戶在10秒之內只能向service提交一次請求,重復的請求直接返回。
如此限流,用腳本寫for循環搶購的請求,99%又被攔住了。
又有人要說了,同一個uid確實被攔住了,那萬一有一個黑客,控制了10W個賬號,10W個uid同時搶手機,該怎么辦呢?
第三步,service服務層攔截。
系統上線,一般都做過壓測,對service的服務能力是清楚的,假如每秒只能服務1W的吞吐,中間可以加一個MQ,采用拉模式來做削峰填谷,service根據自己的服務能力去處理請求,對自己實施保護。
又有人要說了,萬一沒做過壓測,不知道service的服務能力怎么辦?
業務層面,我們知道手機的庫存量,假如庫存只有5K部手機,放過去10W個請求,沒有意義。還是加一個MQ,還是采用拉模式來做削峰填谷,service根據庫存情況去處理請求,對自己實施保護。
如此限流,只有非常少的讀寫請求,會壓到后端數據層。
最后,數據層怎么優化?
如果做了前端,站點層,服務層的優化,數據庫上的壓力就很小了:
- 沒有數據量大的問題,不需要做水平切分;
- 沒有吞吐量大的問題,系統根據自身壓力,根據業務庫存來保護自己;
數據庫層閑庭信步,最多加加緩存抗一下查詢壓力,單機也能扛得住。
如果有多SKU,可以根據壓力情況與SKU情況加機器拆分,總之系統具備線性擴容能力。
總結
還是那句話:盡量將請求攔截在系統的上游,而不要壓到庫存數據。
知其然,知其所以然。
思路比結論更重要。