秒殺系統優化思路
一、秒殺業務為什麽這麽難做
秒殺系統,庫存只有一份,所有人會在集中的時間讀和寫這些數據。
例如:
- 小米手機每周二的秒殺,可能手機只有1萬部,但瞬間進入的流量可能是幾百幾千萬。
- 12306搶票,票是有限的,但是搶票的人很多,都讀取相同的庫存。讀寫沖突,鎖非常嚴重,這是業務難的地方。
那我們怎麽優化秒殺業務呢?
二、優化方向
(以上的兩個場景要優化有兩個方向)
- 將請求盡量攔截在系統上遊(不要讓鎖沖突落到數據庫上去)。傳統的秒殺系統之所以掛,是因為請求都壓到後端數據層,數據讀寫沖突嚴重,並發高響應慢,幾乎所有請求都超時,流量最大,下單成功的有效流量非常小。以12306為例,一趟火車其實只有2000張票,但是搶到的人卻有200萬,基本沒人能買票成功,請求有效率為0.
- 充分利用緩存,秒殺買票,這是一個典型的讀多寫少的應用場景,大部分請求是車次/票查詢,下單和支付才是寫請求。一趟火車只有2000張票,200萬人來買,最多2000人下單成功,其他人都是查庫存,寫入操作的比例是0.1%,而讀取的操作比例是99.9%,非常適合緩存來做優化。
三、常見秒殺架構
常見的秒殺架構基本是這樣的
- 瀏覽器端,最上層,會執行一些JS代碼
- 站點層,這一層會訪問後端數據,將操作響應返回給瀏覽器
- 服務層,向上遊屏蔽底層數據細節,提供數據訪問
- 數據層,最終的“庫存”會存放在這裏,mysql是一個典型(當然還有緩存),這張圖雖然簡單,但是能形象的說明大流量高並發的秒殺業務架構(根據筆者從業的經驗,基本所有公司的軟件架構都脫離不了這幾層,大同小異),後面詳細解 析各層級怎麽優化。
四、各層優化細節
- 第一層:客戶端怎麽優化(瀏覽器層,APP層)
大家應該都玩過微信搖一搖搶紅包,是每一次搖一搖,就會往後端發送請求麽?
回顧一下我們12306剛出來那年搶票的場景,點擊“查詢”按鈕之後,系統卡在那裏或者響應非常慢,這時用戶就會再次點擊”查詢“,繼續點點點,可是這樣有用麽?徙增系統負載,如果真實購買用戶只有200W,那一個用戶多點擊5次,
就有1000萬,多出來80%的用戶怎麽整?
-
- 產品層面優化:用戶點擊查詢或者購票操作後,按鈕置灰,禁止用戶重復提交。
- JS層面優化:限制用戶在x秒內只能提交一次請求。
上面說到搖紅包,就算我們瘋狂的把手機甩飛了,系統也只是在x秒才向系統發送請求。
這就是所謂的“將請求盡量攔截在系統上遊”,越上遊越好,瀏覽器層,APP層就給攔住,這樣就擋住了多出那80%的用戶請求。
但是,這種辦法只能攔截住普通的用戶,對於高端的程序猿們來說是攔不住的,firebug一抓包,http長啥樣都知道了,js是攔不住程序員寫for循環調用http接口的,這部分請求如何處理?
- 第二層:站點層面的請求攔截
怎麽防止程序猿們for循環請求呢?有去重依據麽?ip?cookie-id?這類“秒殺”業務都需要登錄,用我們加了密的uid即可。在站點層面,對uid進行請求計數和去重,一個uid在5秒內只允許1個請求(例如生成uid時加入時間戳),
這樣就可以攔截住程序猿們的for循環請求。
5秒只透過一個請求,那其他請求怎麽辦?緩存,頁面緩存,同一個uid訪問頻度做頁面緩存,x秒內到達站點請求,均返回同一個頁面。 如此限流,既能保證用戶體驗又能保證系統的健壯性。
(頁面緩存不一定要保證所有站點返回一致的頁面,直接放在每個站點的內存也可以,優點是簡單。缺點是http請求落到不同的站點,返回的車票數據可能不一樣。)
這是站點層請求攔截和緩存的優化
如果,有黑客控制了10萬個肉雞,不同的uid,同時發送請求的話,我們怎麽辦?站點層按照uid限流已經攔截不住了。
- 第三層:服務層攔截
(反正不要讓請求落到數據層上)
服務層如何來攔截呢?請求隊列,對於寫入操作的請求,每次只透有限的請求去數據層,這個有限取決於有多少部小米手機或多少張火車票。如果庫存不夠則全部返回“已售完”。
對於讀取的請求如何優化?用cache抗 ,不管是mecached還是redis,單機抗個每秒10萬都沒問題,如此限流,只有非常少的寫入請求,和非常少的讀取緩存mis的請求會透到數據層去,又有99.9%的請求被攔住了。
- 第四層:數據層
瀏覽器攔截了80%,站點層攔截了99.9%並做了頁面緩存,服務層又做了請求隊列與數據緩存,每次透到數據層的請求都是可控的。db基本沒什麽壓力了,還是那句話,庫存是有限的,透這麽多請求來數據庫沒有意義。
全部透到數據庫,100萬個下單,0個成功,透3000到數據庫,全部成功。請求有效率為100%。
總結:
再重復一下關於秒殺系統的兩個優化思路:
- 盡量將請求攔截在系統上遊(越上遊越好)
- 讀多寫少的應用多使用緩存(緩存抗讀壓力)
- 瀏覽器和APP:做限速
- 站點層:按照uid限速,做頁面緩存
- 服務器:按照業務做寫請求隊列控制流量,做數據緩存
- 數據層:閑庭信步
- 並且結合業務做優化。
文章內容來源於微信公眾號“架構師之路”,歡迎大家關註。
我在文章中看到了幾個技術點:memcache,請求隊列。有時間我好好研究一下,再整理到自己的博客上。
如果大家有什麽好的想法,可以留言,我肯定會學習並實踐好再拿出來分享。
非常感謝。
如果對您有幫助,請點贊!
秒殺系統優化思路