秒殺系統瞬時百萬并發流量的六種應對之道
架構
- 本章難度:★★★☆☆
- 本章重點:全面闡述建設秒殺系統挑戰的應對之道,知己知彼,方案了然于胸,自然有應對之道。經過長期秒殺大促的沉淀與總結,針對秒殺系統存在高并發大流量的挑戰,冰河沉淀出六種應對之道:分離、限流、快速響應、準確一致、穩定可靠、全鏈路壓測。
大家好,我是冰河~~
雖然建設秒殺系統的過程中存在著諸多的挑戰,但是這些挑戰都是有應對之道的,對于整個過程中遇到的難點和痛點,都是會沉淀出對應的解決方案。
一、前言
在前面的文章中,詳細闡述了建設秒殺系統的目標與存在的挑戰,并且簡單羅列了如何應對這些挑戰的方式。本章,就詳細闡述對秒殺系統存在挑戰的應對之道,最終構建出兼具高并發、高性能和高可用的秒殺系統。心中不僅了解建設秒殺系統存在的挑戰,更清楚的知道這些挑戰的應對之道,正所謂:知己知彼,百戰不殆,方案了然于胸,自然有應對之法。
二、本章訴求
一般一套成熟并且穩定、經得起實際大促場景考驗的秒殺系統,都是經過不斷迭代、優化和演化而來的。對于設計和研發秒殺系統的技術人員來說,心中一定要清晰的知曉建設秒殺系統存在的挑戰,以及針對這些挑戰的應對之法。
三、應對之道
對于秒殺系統,站在技術人員的角度,相信大家多多少少對秒殺系統有所了解了。既然建設秒殺系統存在著種種的困難和挑戰,那我們就需要從整體上分析這些挑戰的應對之法,而不是在真正開發秒殺系統時,再去臨時想方案,查漏補缺,切忌頭痛醫頭、腳痛醫腳。
從總體上說,我們應對秒殺系統挑戰時,心中要有一桿秤,在設計秒殺系統時,一定要做到分離、削峰限流、快速響應、準確一致、穩定可靠、全鏈路壓測。
接下來,就針對每種應對之道進行詳細的闡述。
四、分離之道
分離之道中,重點在于一個“分”字,主要包括:前后端資源分離、接口分離,數據分離、業務分離、系統分離、流量分離。
4.1 資源分離
資源分離,主要指的是前后端的資源分離。目前,除了一些非常老舊的系統之外,一般在開發互聯網項目過程中,都會采用前后端分離的架構模式,這也是比較普遍的做法。在秒殺系統中,將前端資源分離出來,部署時可以直接推送到CDN服務器,CDN服務器全國各地都有,用戶在訪問系統時,可以從就近的CDN服務器上拉取對應的資源,能夠極大的增強系統的性能。
4.2 接口分離
接口分離包含兩個方面:一個是秒殺接口與其他接口分離,一個是高頻訪問接口與低頻訪問接口分離。
對于秒殺系統的接口來說,在設計上一定要與其他的接口進行分離,不要讓秒殺系統的接口與其他業務的接口互相關聯引用,避免秒殺系統的瞬時高并發流量對其他接口造成影響。
就秒殺系統而言,并不是每個接口的訪問頻次都一樣,一本情況下,商品詳情頁、結算頁和秒殺下單接口的訪問頻次要遠遠大于支付接口的訪問頻次。在設計上一定要將這些接口進行區分隔離,對高頻訪問的接口進行單獨的性能優化。
4.3 數據分離
數據分離也會包含兩個方面:一個是秒殺數據與其他數據分離,一個是動態數據與靜態數據分離。
一般情況下,秒殺數據瞬時的增長率會遠遠大于其他數據,在數據上進行分離,可以對秒殺數據的存儲設施進行單獨的針對性優化,不能讓秒殺數據對其他數據產生影響,在數據層面對秒殺系統進行專有部署。
就秒殺系統而言,本身也會存在著動態數據和靜態數據。動態數據在秒殺期間會容易發生變更,比如秒殺系統的品類、商品的庫存和上下架的狀態等,都是的動態數據,這些動態數據對時間比較敏感。而像秒殺結果等與用戶本身相關的一些數據,可以稱為靜態數據,因為這些數據在整個秒殺活動期間,基本不會發生變化。
在設計上,需要對這些動態數據和靜態數據進行分離,因為數據的更新頻率不同,在優化手段和架構設計上也會存在著差異。對動態數據和靜態數據進行分離后,也可以將服務端產生的靜態數據推送到CDN。
4.4 業務分離
秒殺業務不同于普通的商城業務,秒殺業務的特點就是流量大、持續的時間短,在設計秒殺系統時,需要充分考慮到不同業務之間的影響,做到秒殺業務與其他業務之間的分離。
4.5 系統分離
秒殺系統與其他系統不同,秒殺系統需要承接瞬時高并發流量,而其他大部分系統的流量則比較平緩。一旦將秒殺系統和其他業務系統部署到一起的話,勢必會對其他業務系統造成比較大的影響,所以,需要將秒殺系統與其他業務系統進行分離處理。
在系統分離層面,一般在大廠的秒殺系統中會將秒殺詳情頁系統、秒殺結算頁系統、購物車系統和訂單系統進行分離,并且會申請單獨的域名和負載均衡器等,并且會對相應的微服務集群進行分組隔離。
4.6 流量分離
看到這里,相信大家對秒殺系統的印象更加深刻了。沒錯,秒殺系統的瞬時流量是巨大的,如果秒殺系統的流量與其他業務系統的流量不加以分離處理,其他系統勢必會由于巨大的瞬時流量而導致各種連鎖問題,所以,在設計上,務必將秒殺系統與其他業務系統的流量進行分離。
五、限流之道
限流主要是對流量進行限制,對于秒殺這種業務場景來說,流量是瞬時且巨大的,期間流量會在幾秒鐘之內爬升到峰值,然后馬上又掉下來,形成巨大的毛刺峰值,對系統費資源的消耗也是瞬時且巨大的,需要對這些流量進行限制和管控。通常的應對方法主要有:提前預約秒殺、打散客戶端流量、消息隊列、網關限流、API限流、應用層限流、安全校驗、活動校驗,秒殺商品校驗、秒殺資格校驗、風控校驗,大廠策略。
5.1 提前預約秒殺
為秒殺系統設計一個預約功能,或者單獨設計一個預約系統,用戶要想參與秒殺搶購,則需要提前預約商品的搶購,這樣可以在參與搶購的用戶基數上進行控制,能夠提前鎖定參與秒殺搶購的用戶,而不是整個平臺中所有的用戶都能參與搶購。這樣可以通過將搶購的用戶訪問控制在預約人數之內,在一定程度上能夠大大減少秒殺的峰值流量,對秒殺系統起到一定的防護作用。
5.2 打散客戶端流量
一般秒殺系統的客戶端也會包含:PC、H5、App和小程序,作為秒殺流量的入口,可以在這些入口端設置答題、驗證碼和滑塊等方式將流量打散,因為每個人輸入問答題答案、驗證碼和滑塊的手速不同,就會將瞬時的大并發流量分散到一小段時間內。在秒殺的場景中,不要小看這些處理方式,即使將流量分攤到一秒或者幾百毫秒的時間內,也會將流量峰值降低一個甚至幾個量級。
例如,在沒有將客戶端瀏覽打散的情況下,流量峰值為100萬QPS,使用答題、驗證碼和滑塊的方式將流量打散后,流量峰值可能就會下降到80萬QPS、60萬QPS甚至更低,對秒殺系統能過起到有效的防護作用。
另外,使用問答題、驗證碼和滑塊的方式也能夠快速攔截部分刷單流量、防止機器作弊,起到一定的防刷作用。
注意:目前像阿里這樣的頭部電商平臺,已經不會在客戶端使用問答題、驗證碼和滑塊等方式將流量打散,更傾向于采用非公平的策略,使用有損逐級限流和分層過濾的方式來達到系統限流的目的。
5.3 消息隊列
使用消息隊列來削峰填谷,通過消息隊列可以將同步的請求改造成異步請求,將超過下游系統處理范圍的流量暫時存入消息隊列中,下游的系統可以根據自身處理數據的性能來消費隊列中的數據。
使用消息隊列對搶購下單異步化之后,前端不能及時知曉秒殺的結果數據,需要前端定期查詢秒殺的結果數據反饋給用戶。在使用消息隊列設計異步搶購流程時,有個小技巧:就是前面的請求將商品的庫存消耗完之后,在商品庫存的緩存中設置一個特殊占位符,讓后續的請求能夠快速失敗,而不再進行后續的業務邏輯處理。
可以使用RocketMQ、Kafka和RabbitMQ等消息中間件來實現請求的異步化和削峰填空,具體使用哪種消息中間件可以根據自身業務進行實際評估。
5.4 網關限流
網關一般是一個系統的入口,可以在網關層對流量進行限流,對超出當前系統流量閾值的請求根據一定的策略進行處理,例如拒絕超出當前系統流量閾值的請求,快速返回失敗,也可以將超出閾值的流量緩存起來進行排隊,按照一定的順序消費這些請求,會對下游的業務系統起到一定的防護作用。
5.5 API限流
API限流也就是對接口進行限流,可以使用Google提供的RateLimiter開源包,實現對應的限流策略,在系統中具體的API代碼里進行限流。這種方式可以做到針對特定的API接口進行限流。
5.6 應用層限流
應用層的限流可以通過對線程池的限流來實現,實現線程池的限流時,主要是設置并發數限流,可以通過自定義線程池,配置最大的連接數,以請求隊列的長度和拒絕策略等參數進行限流,如果隊列已滿,并且已經達到最大的線程數,多余的請求就會根據具體的拒絕策略進行處理,以達到限流的目的和效果。
5.7 安全校驗
安全校驗就是要識別出請求的流量哪些是安全流量,哪些是不安全的流量,這里說的不安全的流量指的是友商、黃牛黨或者不懷好意的用戶發起的刷單流量、CC攻擊等,這種流量對系統是有害的,能夠消耗大量的系統資源,為系統造成比較大的壓力,并且這種方式擠占了正常搶購的通道,對正常參與秒殺活動的用戶是不公平的。
5.8 活動校驗
活動校驗就是接收到請求時,對活動數據進行校驗,核對活動是否已經結束、是否下架等等,如果活動已經結束或者已經下架,則在緩存中設置特殊的占位符,對后續的請求進行快速失敗處理,不再進行后續的邏輯處理。
做活動校驗的原因是用戶在客戶端看到活動有效,當流量達到服務端時,活動可能已經結束或者失效了,所以需要做活動的校驗處理。
5.9 秒殺品校驗
秒殺品校驗就是在接收到請求時,對當前的商品信息進行校驗,核對當前商品是否有效,庫存是否充足等。如果商品不再有效、或者庫存已經消耗完畢,則在緩存中設置特殊的占位符,對后續的請求進行快速失敗處理,不再進行后續的邏輯處理。
做秒殺品校驗的原因是用戶在客戶端看到活動有效,當流量達到服務端時,秒殺品可能已經結束或者失效了,所以需要做秒殺品的校驗處理。
5.10 秒殺資格校驗
秒殺資格校驗主要是對參與秒殺的用戶的資格進行校驗,比如設計了預約環節時,只有提前預約過秒殺搶購的用戶才能參與秒殺。再比如,針對當前活動設置了只能秒殺一次的用戶,如果當前用戶存在本次活動的秒殺記錄,就不再允許二次秒殺等等。還有就是如果對秒殺品設置了只針對某些地區開放秒殺活動,則需要判斷用戶的所在地是否在開放的地區,如果不在開放秒殺的地區,則不允許搶購等等。
另外,在秒殺的資格校驗上,可能存在同一個用戶不斷偽造請求的現象,需要加強用戶唯一身份的校驗等邏輯。
5.11 風控校驗
一個成熟穩定的秒殺系統的背后會接入風控系統,對整個秒殺活動進行風控處理,風控系統的建設不是一朝一夕就能完成的,建立風控的過程也是比較困難的,這需要建立在大量數據的基礎之上,不斷的完善用戶的畫像,需要通過復雜的業務場景的考驗,不斷的修正風控模型。
5.12 大廠策略
像阿里這種頭部互聯網公司,其秒殺系統處了會使用上述限流之道進行系統限流外,其處于兼顧用戶體驗和系統資源的考慮,一般不會采用問答題、驗證碼或者滑塊的方式來打散客戶端流量,更傾向于采用非公平的策略,使用有損逐級限流和分層過濾的方式來達到系統限流的目的。
六、快速響應之道
秒殺的場景雖然是高并發、大流量的業務場景,但是在秒殺場景中,需要快速響應用戶的請求,不能讓用戶出現長時間等待的情況,這就需要在秒殺系統的設計上采用一定的策略。對于快速響應來說,可以從多用緩存、本地緩存、分布式緩存、數據盡量少、計算盡量少和流程盡量簡單幾個方面進行設計。
6.1 多用緩存
像秒殺這種在高并發大流量場景下要求極致體驗的系統,緩存是必不可少的,無論是對前端資源還是對后端數據來說,使用緩存都能夠極大的提升系統的性能。同時,使用緩存也能夠對系統進行一定的防護。
如果系統中沒有使用緩存,或者發生了緩存穿透或者雪崩,瞬時的大量請求直接打到數據庫,那數據庫連接會被瞬間耗盡而導致不可用,進而導致嚴重的連鎖反應,整個系統都會被拖垮,所以,使用緩存是非常重要的。
6.2 本地緩存
在秒殺系統中,為了進一步提升系統的性能,會將一部分非常熱點的數據緩存在本地的JVM內存中,接收到請求后,會先從本地緩存中獲取數據,如果本地緩存不存在要獲取的數據,就會到分布式緩存中進行查詢。
6.3 分布式緩存
除了本地緩存外,分布式緩存也是秒殺系統必不可少的,本地緩存的數據有限,只能緩存一部分極度熱點的數據,并且這些極度熱點的數據開始在本地緩存中也不一定存在,這就需要分布式緩存的存在,如果本地緩存中沒有數據,就到分布式緩存查詢,盡最大努力提升系統的性能。
6.4 數據盡量少
對于提升系統的響應性能來說,光有緩存還不夠,還要在處理的數據上要盡量少,不要查詢或者返回無關緊要的數據。因為緩存只是提升了IO的執行效率,但是除了要提升IO的執行效率,還要提升數據在網絡中的傳輸效率、以及內存和磁盤的讀寫效率。這些都要求我們處理的數據要盡量少。
6.5 計算盡量少
除了數據盡量少以外,對于數據的計算操作也要盡量少,盡量不涉及復雜的計算操作,復雜的計算操作會消耗大量的CPU資源,會極大的影響系統的響應性能。
6.6 流程盡量簡單
秒殺系統在流程設計中要盡量簡單,不要涉及到復雜的業務流程,流程越簡單,處理的業務邏輯越少,性能就越高效。
七、準確一致之道
緩存是秒殺系統必不可少的,但是使用緩存之后,就會出現數據一致性的問題,這些數據一致性的問題,就是需要考慮和處理的,主要包含:緩存與數據庫一致、本地緩存與分布式緩存一致、商品庫存與訂單數據一致、前端與后端數據一致。
7.1 緩存與數據庫一致
使用緩存能夠極大的提升系統的性能,但是使用了緩存之后,需要在確保緩存中的數據和數據庫中的數據是一致的。這種一致性需要根據場景決定是強一致性還是弱一致性,亦或是最終一致性。
7.2 本地緩存與分布式緩存一致
本地緩存和分布式緩存都能夠提升數據的性能,對于極度熱點數據來說,最好是存儲在本地緩存中來提升系統的性能,但是這就需要考慮本地緩存與分布式緩存數據的一致性問題。
7.3 商品庫存與訂單一致
這里說的商品庫存與訂單一致,指的是商品已經消耗的庫存數量與訂單中的商品數量一致,不能出現超賣問題,這就需要在秒殺系統的設計中,充分考慮到商品庫存的扣減問題。
7.4 前端與后端數據一致
前端與后端的數據一致,指的是在秒殺過程中盡量做到前端的數據與后端的數據保持一致,這里說的一致,就不是強一致了,而是最終一致。因為參與秒殺的用戶很多,可能會出現某個用戶在客戶端看到的商品庫存剩余100件,發起秒殺搶購的請求后,請求發送到服務端,服務端檢測到商品庫存已經耗光,就會返回庫存不足或者秒殺已結束的提示,這種場景就可以歸類為最終一致。
八、穩定可靠之道
一個系統的穩定性是重中之重要考慮的問題,一個秒殺系統必須要具備高度的穩定性,要想滿足系統的穩定性,可以從隔離策略和監控的角度來保證系統的穩定性。隔離可以從業務隔離、系統隔離和數據隔離的角度進行考慮,監控就可以從監控數據庫與基礎指標、JVM指標和中間件等指標的角度進行考慮。
8.1 業務隔離
秒殺系統在業務上與其他系統進行隔離,對于參與秒殺的商品來說,一般會在秒殺活動開始前,提前進行提報,并且指定詳細的營銷策劃和方案。對于參與用戶來說,提前預約,可以提前識別流量和系統的并發數,根據具體情況評估是否需要擴容、是否需要降級或者調整限流策略。
8.2 系統隔離
對于被流量沖擊比較大的核心系統進行物理隔離,鏈路末端的系統,經過前面的削峰限流之后,流量就比較可控了,可以不做物理隔離,在邏輯上進行隔離即可。在大廠中,一般會將秒殺的商詳頁系統、秒殺結算頁系統、購物車系統和訂單系統單獨隔離出來。
8.3 數據隔離
對于秒殺系統的數據服務,例如Redis集群、MySQL集群等要單獨隔離部署,做到秒殺數據與其他業務數據的隔離。
除此之外,還要將流量正確的路由到秒殺專有的環境中。
8.4 監控數據庫與基礎指標
除了通過隔離策略增強系統的穩定性之外,還要時刻關注系統的風險指標,對數據庫、CPU使用率、內存使用率、負載、網卡、磁盤、IO、網絡波動等進行監控。
8.5 監控JVM指標
監控JVM的指標可以包含:Young GC和Full GC的次數和耗時,線程池的線程數和等待隊列,運行中的線程,死鎖的線程,以及JVM的堆棧使用情況等等。
8.6 監控中間件指標
監控中間件的指標,一般情況下可以緩存的容量、QPS和RT進行監控,對于數據庫的QPS、容量和連接池進行監控,對消息中間件的QPS、RT以及消息的堆積情況進行監控,對整個交易鏈路的分支系統進行監控等等。
九、全鏈路壓測之道
對于秒殺這種系統高并發、大流量的系統來說,單一的測試功能和對交易鏈路上某一部分功能都不能測試出整個秒殺系統的性能瓶頸點,要知道木桶能不能裝滿水是取決于最短的木板,對于系統來說也是,整體性能也是取決于整個交易鏈路上性能最低的一環。所以,需要對秒殺系統進行全鏈路壓測。根據實際壓測出來的數據進行針對性的優化和調整。
十、總結
本章,主要是對秒殺系統高并發大流量的挑戰給出了應對之道,從總體上說,我們應對秒殺系統挑戰時,心中要有一桿秤,在設計秒殺系統時,一定要做到分離、削峰限流、快速響應、準確一致、穩定可靠、全鏈路壓測。