秒殺活動的技術挑戰(zhàn)
1. 對現(xiàn)有網(wǎng)站業(yè)務造成沖擊
秒殺活動只是網(wǎng)站營銷的一個附加活動,這個活動具有時間短,并發(fā)訪問量大的特點,如果和網(wǎng)站原有應用部署在一起,必須會對現(xiàn)有業(yè)務造成沖擊,稍有不慎可能導致整個網(wǎng)站癱瘓。
2. 高并發(fā)下的應用、數(shù)據(jù)庫負載
用戶在秒殺開始前,通過不停刷新瀏覽器頁面以保證不會錯過秒殺,這些請求如果按照一般的網(wǎng)站應用架構,訪問應用服務器、連接數(shù)據(jù)庫,會對應用服務器和數(shù)據(jù)庫服務器造成極大的負載壓力。
3. 突然增加的網(wǎng)絡及服務器帶寬
假設商品頁面大小200K(主要是商品圖片大?。?,那么需要的網(wǎng)絡和服務器帶寬是2G(200K×10000),這些網(wǎng)絡帶寬是因為秒殺活動新增的,超過網(wǎng)站平時使用的帶寬。
4. 直接下單
秒殺的游戲規(guī)則是到了秒殺時間才能開始對商品下單購買,在此時間點之前,只能瀏覽商品信息,不能下單。而下單頁面也只是一個普通的URL,如果得到這個URL,不用等到秒殺開始就可以下單了。
秒殺系統(tǒng)的應對策略
1. 秒殺系統(tǒng)獨立部署
為了避免因為秒殺活動的高并發(fā)訪問而拖垮整個網(wǎng)站,使整個網(wǎng)站不必面對蜂擁而來的用戶訪問,可將秒殺系統(tǒng)獨立部署;如果需要,還可以使用獨立的域名,使其與網(wǎng)站完全隔離,即使秒殺系統(tǒng)崩潰了,也不會對網(wǎng)站造成任何影響。
2. 秒殺商品頁面靜態(tài)化
重新設計秒殺商品頁面,不使用網(wǎng)站原來的商品詳情頁面,頁面內容靜態(tài)化:將商品描述、商品參數(shù)、成交記錄和用戶評價全部寫入一個靜態(tài)頁面,用戶請求不需要經(jīng)過應用服務器的業(yè)務邏輯處理,也不需要訪問數(shù)據(jù)庫。所以秒殺商品服務不需要部署動態(tài)的Web服務器和數(shù)據(jù)庫服務器。
3. 租借秒殺活動網(wǎng)絡帶寬
因為秒殺新增的網(wǎng)絡帶寬,必須和運營商重新購買或者租借。為了減輕網(wǎng)站服務器的壓力,需要將秒殺商品頁面緩存在CDN,同樣需要和CDN服務商臨時租借新增的出口帶寬。
4. 動態(tài)生成隨機下單頁面URL
為了避免用戶直接訪問下單頁面URL,需要將該URL動態(tài)化,即使秒殺系統(tǒng)的開發(fā)者也無法在秒殺開始前訪問下單頁面的URL。辦法是在下單頁面URL加入由服務器端生成的隨機數(shù)作為參數(shù),在秒殺開始的時候才能得到。
秒殺系統(tǒng)架構設計
秒殺系統(tǒng)為秒殺而設計,不同于一般的網(wǎng)購行為,參與秒殺活動的用戶更關心的是如何能快速刷新商品頁面,在秒殺開始的時候搶先進入下單頁面,而不是商品詳情等用戶體驗細節(jié),因此秒殺系統(tǒng)的頁面設計應盡可能簡單。
商品頁面中的購買按鈕只有在秒殺活動開始的時候才變亮,在此之前及秒殺商品賣出后,該按鈕都是灰色的,不可以點擊。
下單表單也盡可能簡單,購買數(shù)量只能是一個且不可以修改,送貨地址和付款方式都使用用戶默認設置,沒有默認也可以不填,允許等訂單提交后修改;只有第一個提交的訂單發(fā)送給網(wǎng)站的訂單子系統(tǒng),其余用戶提交訂單后只能看到秒殺結束頁面。
除了上面提到的秒殺系統(tǒng)的技術挑戰(zhàn)及應對策略,還有一些其他問題需要處理。
1. 如何控制秒殺商品頁面購買按鈕的點亮
購買按鈕只有在秒殺開始的時候才能點亮,在此之前是灰色的。如果該頁面是動態(tài)生成的,當然可以在服務器端構造響應頁面輸出,控制該按鈕是灰色還是點亮,但是為了減輕服務器端負載壓力,更好地利用CDN、反向代理等性能優(yōu)化手段,該頁面被設計為靜態(tài)頁面,緩存在CDN、反向代理服務器上,甚至用戶瀏覽器上。秒殺開始時,用戶刷新頁面,請求根本不會到達應用服務器。
解決辦法是使用JavaScript腳本控制,在秒殺商品靜態(tài)頁面中加入一個JavaScript文件引用,該JavaScript文件中包含秒殺開始標志為否;當秒殺開始的時候生成一個新的JavaScript文件(文件名保持不變,只是內容不一樣),更新秒殺開始標志為是,加入下單頁面的URL及隨機數(shù)參數(shù)(這個隨機數(shù)只會產生一個,即所有人看到的URL都是同一個,服務器端可以用redis這種分布式緩存服務器來保存隨機數(shù)),并被用戶瀏覽器加載,控制秒殺商品頁面的展示。這個JavaScript文件的加載可以加上隨機版本號(例如xx.js?v=32353823),這樣就不會被瀏覽器、CDN和反向代理服務器緩存。
這個JavaScript文件非常小,即使每次瀏覽器刷新都訪問JavaScript文件服務器也不會對服務器集群和網(wǎng)絡帶寬造成太大壓力。
2. 如何只允許第一個提交的訂單被發(fā)送到訂單子系統(tǒng)
由于最終能夠成功秒殺到商品的用戶只有一個,因此需要在用戶提交訂單時,檢查是否已經(jīng)有訂單提交。如果已經(jīng)有訂單提交成功,則需要更新JavaScript文件,更新秒殺開始標志為否,購買按鈕變灰。事實上,由于最終能夠成功提交訂單的用戶只有一個,為了減輕下單頁面服務器的負載壓力,可以控制進入下單頁面的入口,只有少數(shù)用戶能進入下單頁面,其他用戶直接進入秒殺結束頁面。假設下單服務器集群有10臺服務器,每臺服務器只接受最多10個下單請求。在還沒有人提交訂單成功之前,如果一臺服務器已經(jīng)有十單了,而有的一單都沒處理,可能出現(xiàn)的用戶體驗不佳的場景是用戶第一次點擊購買按鈕進入已結束頁面,再刷新一下頁面,有可能被一單都沒有處理的服務器處理,進入了填寫訂單的頁面,可以考慮通過cookie的方式來應對,符合一致性原則。當然可以采用最少連接的負載均衡算法,出現(xiàn)上述情況的概率大大降低。
小結
秒殺是對網(wǎng)站架構的極大考驗,在難以預計和控制的高并發(fā)訪問的沖擊下,稍有不慎,系統(tǒng)就會被用戶秒殺,導致整個系統(tǒng)宕機,活動失敗,構成重大事故。因此在遵循秒殺活動游戲規(guī)則的基礎上,為了保證系統(tǒng)的安全,保持適度的公平公正即可。即使系統(tǒng)出了故障,也不應該給用戶顯示出錯頁面,而是顯示秒殺活動結束頁面,避免不必要的困擾。
本文摘自李智慧的《大型網(wǎng)站技術架構:核心原理與案例分析》,對文中的內容做了一點細化與補充。