亚洲中文字幕无码日韩精品,亚洲一区制服无码中字,亚洲精品第一国产综合精品99 ,一本大道中文日本香蕉

微立頂科技

新聞資訊

創(chuàng)新 服務 價值

  秒殺系統(tǒng)設計探析

發(fā)布日期:2022/9/25 23:51:49      瀏覽量:

一、秒殺是什么?

秒殺系統(tǒng)的業(yè)務邏輯和復雜程度都被大眾熟知,其實主要解決的問題有兩個——高并發(fā)和一致性。其中高并發(fā)又分為讀和寫,要減少用戶從服務端讀取數(shù)據(jù),控制數(shù)據(jù)的傳輸大??;寫則需要獨立處理數(shù)據(jù)庫。一致性是指保證庫存數(shù)據(jù)的準確,超賣和超買都是不能出現(xiàn)的。至于高可用會在最后介紹,通過高可用可以保證流量超出預期或其他外情況發(fā)生時,秒殺活動的順利完成。

 綜上所述,秒殺系統(tǒng)是一個要滿足高并發(fā)、強一致、高可用的分布式系統(tǒng)。

二、秒殺架構的設計要素

針對秒殺系統(tǒng)的架構設計需要考慮以下幾個要素:

1.減少讀的次數(shù)

這里提到的讀不止是數(shù)據(jù),還有靜態(tài)資源的讀取。

為什么要減少讀的次數(shù)呢,因為網(wǎng)絡傳輸是需要時間的,無論是請求、處理、響應都需要服務器處理。如果存在必須讀取的情況,要減小數(shù)據(jù)請求和響應的大小,數(shù)據(jù)在數(shù)據(jù)庫和各種服務之間調用的過程中存在序列化和反序列化的過程,這是很消耗資源的。

靜態(tài)資源的讀取比較常見的優(yōu)化手段就是合并CSS和JS文件,要保證請求的靜態(tài)文件在統(tǒng)一域名中,并減少訪問次數(shù)。每次HTTP請求都存在網(wǎng)絡傳輸,減少耗時是很有必要的。

2.減少服務調用節(jié)點

這里提到的節(jié)點是指用戶請求后,直至響應完成所經歷的服務節(jié)點。不同節(jié)點間,尤其是不同機架,不同機房節(jié)點間的服務調用不僅僅耗時,還會降低秒殺的可靠性。

3.減少不必要的秒殺非核心業(yè)務

秒殺業(yè)務可以根據(jù)重要程度賦予權重,減少低權重服務的調用,以防止高權重系統(tǒng)被拖垮。秒殺活動進行時,有很多不是秒殺核心業(yè)務的數(shù)據(jù)可以通過降低優(yōu)先級進行優(yōu)化,例如支付、通知等功能。

以上的原則并不是絕對的,只是在設計中努力優(yōu)化的方向。 

三、秒殺架構的搭建思路

對于并發(fā)量訪問較大的秒殺架構,為了提高架構性能和穩(wěn)定性,需要注意幾點:秒殺要獨立于其他系統(tǒng),無論在研發(fā)和部署環(huán)節(jié)都要獨立,這樣有助于整體平臺的穩(wěn)定性,也有利于秒殺系統(tǒng)的優(yōu)化。秒殺的數(shù)據(jù),尤其是核心數(shù)據(jù)單獨放到緩存系統(tǒng)中,提高并發(fā),對于非核心數(shù)據(jù)可以放到本地,減少請求服務的次數(shù)。秒殺的頁面要實現(xiàn)動靜分離,把頁面刷新頻率降低。

另外,從安全性角度考慮,秒殺的驗證必不可少,限流保護更是重中之重。


這次要解決的是秒殺活動中的動靜分離方案。分離后的數(shù)據(jù)處理就簡單了許多。


 

一、動靜分離是什么?

動靜分離就是并不是傳統(tǒng)意義的靜態(tài)頁面和動態(tài)頁面,而是指是否需要根據(jù)發(fā)送請求的用戶進行個性化數(shù)據(jù)的推送。舉個例子,在訪問一些商城時,會針對不同用戶進行商品的推薦,那么這樣的數(shù)據(jù)就是動態(tài)數(shù)據(jù);商城中有一些熱門的活動,會針對所有用戶進行推送,那么這樣的數(shù)據(jù)就是靜態(tài)數(shù)據(jù),盡管這里的數(shù)據(jù)是動態(tài)生成的。

二、優(yōu)化靜態(tài)數(shù)據(jù):

首先,我們要做的就是優(yōu)化靜態(tài)數(shù)據(jù),那就是通過緩存來提高靜態(tài)數(shù)據(jù)的讀取可以有效提高數(shù)據(jù)的訪問,除此之外還要考慮將緩存服務根據(jù)業(yè)務需要放到用戶本地或CDN上。如何實現(xiàn)緩存將會在后續(xù)提到,我們現(xiàn)在可以認為這里的緩存是一個Redis集群或其他緩存系統(tǒng)。

三、優(yōu)化動態(tài)數(shù)據(jù):

動態(tài)數(shù)據(jù)主要包括服務端的時間,用戶數(shù)據(jù)等。我常用的方法是通過發(fā)起一個Ajax的異步請求,獲取動態(tài)數(shù)據(jù),這樣做的缺點是頁面存在延遲的話,體驗不好。為了解決這個問題,可以通過提前在頁面中的動態(tài)數(shù)據(jù)展示部分做一個插槽,類似vue中的slot,緩解數(shù)據(jù)加載中的突兀感。

四、選擇適合的分離架構:

接下來要介紹兩種分離架構,一種是秒殺活動不頻繁,秒殺商品數(shù)量少的場景,一種是秒殺活動頻繁,秒殺商品數(shù)量多的場景。這里說的兩種架構需要結合自身業(yè)務作取舍,不要一味的追求高并發(fā)。

1.單機部署

這里提到的單機是將緩存在一臺性能較高的實體機中進行分組,采用Hash算法。由于商品數(shù)量不多,緩存的命中率會大大提高。這既是有點也是缺點,提高命中的同時可能會存在緩存擊穿的風險。在訪問量較大時,可以通過修改緩存算法或添加相同的緩存分組來緩解。

單機部署有效的回避了分布式網(wǎng)絡傳輸?shù)膯栴},提高了緩存的命中率。這樣做有效的降低了運維的復雜程度,對于沒有分布式緩存系統(tǒng)的業(yè)務來說,是一個很好的選擇。

2.緩存集群

在一些業(yè)務復雜、數(shù)據(jù)龐大的機構中,可以考慮建立獨立的緩存系統(tǒng),減少運維成本,提高復用。這樣做的可以使開發(fā)人員將重心放在業(yè)務中,不需要考慮緩存數(shù)據(jù)的處理;同時可以通過zookeeper實現(xiàn)配置自動化;在不同秒殺活動中,共享內存,降低資源浪費。

除此之外,CDN的優(yōu)化以后也會介紹。

五、緩存中的數(shù)據(jù):

數(shù)據(jù)處理除了以上提到的動靜分離,還需要進行隔離。這么做的原因是不能讓秒殺活動影響了其他業(yè)務,在秒殺期間減少對其他業(yè)務資源的占用。要做到這一點,除了要進行系統(tǒng)隔離,還需要進行數(shù)據(jù)的隔離,就像我們上一篇中提到的,要有獨立的數(shù)據(jù)存儲。實現(xiàn)數(shù)據(jù)隔離的方式有很多種,可以根據(jù)區(qū)域劃分、可以根據(jù)URL劃分等。

秒殺請求在高度集中在某一個時間點。這樣一來,就會導致一 個特別高的流量峰值,它對資源的消耗是瞬時的 。能夠搶到商品的人數(shù)是有限的,也就是說10人和1000人發(fā) 起請求的結果都是一樣的。也就是說真正開始下單時,秒殺請求并不是越多越好。


一、秒殺中的削峰

由于服務器的處理資源是恒定的,用或者不用它的處理能力都是一樣的,出現(xiàn)峰值的話,很容易導致忙到處理不過來,閑的時候卻又沒有什么要處理。為了保證服務質量,很多處理資源只能按照忙時預估,而這會導致資源浪費。 削峰可以讓服務端處理變得更加平穩(wěn),還可以節(jié)省服務器的資源成本。針對秒殺這一場景,削峰從本質上來說就是更多地延緩用戶請求的發(fā)出,以便減少和過濾掉一些無效請求。

常見秒殺流量削峰的一些操作思路:消息隊列、答題器、數(shù)據(jù)過濾。

1.消息隊列

其中最容易想到的解決方案就是用消息隊列來緩沖瞬時流量,把同步的直接調用轉換成異步的間接推送,通過隊列在一端承接瞬時的流量洪峰,在另一端平滑地將消息推送出去,在這里,消息隊列就像“水庫"一樣,攔蓄上游的洪水,削減進入下游的洪峰流量。

但是,如果流量峰值持續(xù)時間達到了消息隊列的處理上限,消息隊列同樣也會被壓垮,這樣雖然保護了下游的系統(tǒng),但是和直接把請求丟棄也沒多大的區(qū)別。就像遇到洪水爆發(fā)時,即使是有水庫恐怕也無濟于事。在這種情況下,我們要把“一步的操作”變成“兩步的操作”,其中增加的操作用來起到緩沖的作用,例如利用線程池加鎖等待、采用先進先出、先進后出等常用的內存排隊算法。

2.答題器

添加答題器第一個目的是防止部分買家使用秒殺器在參加秒殺時作弊,第二個目的就是延緩請求,起到削峰的作用。把請求的時間從瞬時延長到了幾秒,這樣會大大減輕對服務器的壓力。而且后續(xù)請求到達服務器時已經沒有庫存了,真正的并發(fā)處理就很有限了。

答題器生成的題目不需要很復雜,為了防止被破解可以添加圖片噪點。同時在CDN上緩存圖片,避免成為秒殺活動中的短板,影響用戶體驗。

3.數(shù)據(jù)過濾

這里提到的數(shù)據(jù)過濾有點像某些企業(yè)在招聘時,把簡歷隨機抽出一部分扔掉一樣,只不過抽取的過程可以設置一定的規(guī)則,過濾掉那些無效的請求。在不同的處理層根據(jù)不同的規(guī)則有效的過濾,例如對寫數(shù)據(jù)進行基于時間的合理分片,過濾掉過期的失效請求;對寫數(shù)據(jù)進行強一致性校驗,只保留最后有效的數(shù)據(jù)。

這么做的目的是在讀系統(tǒng)中,盡量減少由于一致性校驗帶來的系統(tǒng)瓶頸,但是盡量將不影響性能的檢查條件提前,如用戶是否具有秒殺資格、商品狀態(tài)是否正常、用戶答題是否正確、秒殺是否已經結束、是否非法請求等;在寫數(shù)據(jù)系統(tǒng)中,主要對寫的數(shù)據(jù)做一致性檢查,最后在數(shù)據(jù)庫層保證數(shù)據(jù)的最終準確性。

二、秒殺中的服務性能優(yōu)化

服務端性能, 一般用QPS來衡量, 還有一個和QPS息息相關的是響應時間, 它可以理解為服務器處理響應的耗時。

正常情況下響應時間越短, 一秒鐘處理的請求數(shù)(QPS) 自然也就會越多, 這在單線程處理的情況下看起來是線性的關系,即我們只要把每個請求的響應時間降到最低,那么性能就會最高。

這個兩個因素到底會造成什么樣的影響?首先, 我們先來看看響應時間和QPS的關系,對于大部分的Web系統(tǒng)而言響應時間一般都是由CPU執(zhí)行時間和線程等待時間組成,也許你會說為什么不去減少這種等待時間,其實減少線程等待時間對提升性能的影響沒有我們想象得那么大, 這點在很多代理服務器上可以做驗證,如果代理服務器本身沒有CPU消耗, 我們在每次給代理服務器代理的請求加個延時, 即增加響應時間,這對代理服務器本身的吞吐量并沒有多大的影響,因為代理服務器本身的資源并沒有被消耗。

真正對性能有影響的是CPU的執(zhí)行時間, 因為CPU的執(zhí)行真正消耗了服務器的資源, 我們應該致力于減少CPU的執(zhí)行時間。

對于Java系統(tǒng)可優(yōu)化的地方很多,除了常見的代碼優(yōu)化外,以下的內容值得注意。

Java和通用的Web服務器相比,在處理大并發(fā)的HTTP請求時要弱一點, 所以一般我們都會對大流量的Web系統(tǒng)做靜態(tài)化改造,讓大部分請求和數(shù)據(jù)直接在Nginx服務器或者Web代理服務器上直接返回 , 而Java層只需處理少量數(shù)據(jù)的動態(tài)請求。

針對這些請求, 我們可以使用以下手段進行優(yōu)化:

1.直接使用Servlet處理請求, 避免使用傳統(tǒng)的MVC框架, 這樣可以繞過一大堆復雜且用處不大的處理邏輯, 直接輸出流數(shù)據(jù)。使用resp.getOutputStream)而不是resp.get Writer函數(shù), 可以省掉一些不變字符數(shù)據(jù)的編碼, 從而提升性能。

2.數(shù)據(jù)輸出時推薦使用JSON而不是模板引擎來輸出頁面。

3.集中式緩存為了保證命中率一般都會采用一致性Hash, 所以同一個key會落到同一臺機器上。那么,該如何徹底解決單點的瓶頸呢? 答案是采用應用層的Local Cache。你需要劃分成動態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)。

像商品中的標題和描述這些本身不變的數(shù)據(jù),會在秒殺開始之前全量推送到緩存直到到秒殺結束。

像庫存這類動態(tài)數(shù)據(jù)的方式緩存一定時間,失效后再去緩存拉取最新的。你可能還會有疑問:像庫存這種頻繁更新的數(shù)據(jù),一旦數(shù)據(jù)不一致,會不會導致超賣? 這就要用到前面介紹的讀數(shù)據(jù)的分層原則了,讀的場景可以允許一定的臟數(shù)據(jù),因為這里的誤判只會導致少量原本無庫存的下單請求被誤認為有庫存,可以等到真正寫數(shù)據(jù)時再保證最終的一致性。 

如果你第一次接觸秒殺,可能還不太理解,庫存100件就賣100件,在數(shù)據(jù)庫里減到0就好了,這有什么麻煩的?理論上是這樣,但是具體到業(yè)務場景中就沒那么簡單了。今天就聊聊減庫存的設計,之后以高可用方案來結束秒殺設計的全部內容。


一、秒殺中的減庫存

減庫存操作一般有如下幾個方式:

1.下單減庫存:下單后,在商品的總庫存中減去購買數(shù)量,下單減庫存是最簡單的減庫存方式,也是控制最精確的一種,下單時直接通過數(shù)據(jù)庫的事務機制控制商品庫存,這樣一定不會出現(xiàn)超賣的情況。

2.付款減庫存:下單后,并不立即減庫存,而是等到付款后才真正減庫存,否則庫存一直保留給其他買家,但因為付款時才減庫存,如果并發(fā)比較高,有可能出現(xiàn)買家下單后付不了款的情況,可能商品已經被其他人買走了。

3.預扣庫存:下單后,庫存為其保留一定的時間, 超過這個時間,庫存將會自動釋放,釋放后其他買家就可以繼續(xù)購買,在買家付款前,系統(tǒng)會校驗該庫存是否還有保留,如果沒有保留,則再次嘗試預扣;如果庫存不足則不允許繼續(xù)付款;如果預扣成功,則完成付款并實際地減去庫存,這種方式相對復雜一些。

以上這幾種減庫存的方式都會存在一些問題。  假如我們采用“下單減庫存”的方式,正常情況下,買家下單后付款的概率會很高,所以不會有太大問題,但是有一種場景例外,就是當賣家參加某個活動時,此時活動的有效時間是商品的黃金售賣時間,通過惡意下單的方式將該賣家的商品全部下單,那么這款商品就不能正常售賣了。要知道,這些惡意下單的人是不會真正付款的。

既然“下單減庫存”可能導致惡意下單,從而影響賣家的商品銷售,那么有沒有辦法解決呢?你可能會想,采用“付款減庫存”的方式是不是就可以了?的確可以,但是 “付款減庫存”又會 導致另外一個問題:庫存超賣。假如有10件商品,因為下單時不會減庫存,就可能出現(xiàn)100人下單成功的情況,這樣一 來,就會導致很多買家下單成功但是付不了款,購物體驗自然比較差。

既然“下單減庫存”和“付款減庫存”都有缺點,我們能否采用“預扣庫存”這種方式呢? 這種方案確實可以在一定程度上緩解上面的問題,但是否就徹底解決了呢?針對惡意 下單這種情況,雖然把有效的付款時間設置為10分鐘,但是惡意買家完全可以在10分鐘后再次下單。

針對這種情況,解決辦法還是要結合反作弊的措施來制止, 例如,設置最大購買件數(shù),對重復下單不付款的操作進行次數(shù)限制等。針對“庫存超賣”這種情況,在10分鐘時間內下單的數(shù)量仍然有可能超過庫存數(shù)量,遇到這種情況只能區(qū)別對待:對普通的商品下單數(shù)量超過庫存數(shù)量的情況,可以通過補貨來解決;但是有些賣家完全不允許庫存為負數(shù)的情況,那只能在買家付款時提示庫存不足。

由于參加秒殺的商品成功下單后卻不付款的情況比較少,再加上賣家對秒殺商品的庫存有嚴格限制,所以秒殺商品采用“下單減庫存”更加合理。一般我們有多種解決方案:一種是在應用程序中通過事務來判斷,即保證減后庫存不能為負數(shù),否則就回滾;另一種辦法是直接設置數(shù)據(jù)庫的字段數(shù)據(jù)為 無符號整數(shù), 這樣減后庫存字段值小于零時會直接執(zhí)行SQL語句來報錯。 

二、秒殺中的高可用

高可用涉及架構階段、編碼階段、測試階段、運行階段。

1.架構階段:架構階段主要考慮系統(tǒng)的可擴展性和容錯性,要避免系統(tǒng)出現(xiàn)單點問題,例如多機房部署,即使某個機房出現(xiàn)整體故障,仍然不會影響整體網(wǎng)站的運轉。

2.編碼階段:編碼最重要的是保證代碼的健壯性,例如涉及遠程調用問題時,要設置合理的超時退出機制,防止被其他系統(tǒng)拖垮。

3.測試階段:測試主要是保證測試用例的覆蓋度,保證最壞情況發(fā)生時,我們也有相應的處理流 程。

4.運行階段:系統(tǒng)大部分時間都會處于運行態(tài),運行態(tài)最重要的是對系統(tǒng)的監(jiān)控要準確及時,發(fā)現(xiàn)問題能夠準確報警并且報警數(shù)據(jù)要準確詳細,以便于排查問題。

 為什么系統(tǒng)的高可用建設要放到整個生命周期中全面考慮?因為我們在每個環(huán)節(jié)中都可能犯錯, 而有些環(huán)節(jié)犯的錯是無法彌補的。例如在架構階段,沒有消除單點問題,那么系統(tǒng) 上線后,遇到突發(fā)流量把單點給掛了,加機器都加不進去。

那么針對秒殺系統(tǒng),我們重點介紹在遇到大流量時,應該從哪些方面來保障系統(tǒng)的穩(wěn)定運行,所 以更多的是看如何針對運行階段進行處理,這就引出了接下來的內容:降級、限流

降級:就是當系統(tǒng)的容量達到一定程度時,限制或者關閉系統(tǒng)的某些非核心功能,從而把有限的資源保留給更核心的業(yè)務。降級方案可以這樣設計:當秒殺流量達到5w/s時,把成交記錄的獲取從展示20條降級到只展示5條。 

執(zhí)行降級無疑是在系統(tǒng)性能和用戶體驗之間選擇了前者,降級后肯定會影響一部分用戶的體驗,。 所以降級的核心目標是犧牲次要的功能和用戶體驗來保證核心業(yè)務流程的穩(wěn)定,是一個不得已而 為之的舉措。

限流: 如果說降級是犧牲了一部分次要的功能和用戶的體驗效果,那么限流就是更極端的一種保護措施 了。限流就是當系統(tǒng)容量達到瓶頸時,我們需要通過限制一部分流量來保護系統(tǒng),并做到既可以人工執(zhí)行開關,也支持自動化保護的措施。

首先,來分別說下客戶端限流和服務端限流的優(yōu)缺點。 客戶端限流,好處可以限制請求的發(fā)出,通過減少發(fā)出無用請求從而減少對系統(tǒng)的消耗,缺點 就是當客戶端比較分散時,沒法設置合理的限流閾值。如果閾值設的太小,會導致服務端沒有 達到瓶頸時客戶端已經被限制;而如果設的太大,則起不到限制的作用。 服務端限流,好處是可以根據(jù)服務端的性能設置合理的閾值,而缺點就是被限制的請求都是無效的請求,處理這些無效的請求本身也會消耗服務器資源。



  業(yè)務實施流程

需求調研 →

團隊組建和動員 →

數(shù)據(jù)初始化 →

調試完善 →

解決方案和選型 →

硬件網(wǎng)絡部署 →

系統(tǒng)部署試運行 →

系統(tǒng)正式上線 →

合作協(xié)議

系統(tǒng)開發(fā)/整合

制作文檔和員工培訓

售后服務

馬上咨詢: 如果您有業(yè)務方面的問題或者需求,歡迎您咨詢!我們帶來的不僅僅是技術,還有行業(yè)經驗積累。
QQ: 39764417/308460098     Phone: 13 9800 1 9844 / 135 6887 9550     聯(lián)系人:石先生/雷先生