秒殺怎麼優化

2021-08-14 15:23:46 字數 2934 閱讀 5070

快到年底了,忽然間又想起了高中時候的班長,他常說臨近年關,都注意安全,感覺心裡暖暖的。行了,話不多說,快到年底,公司業務量增加很快,預計秒殺這塊也會增加很多,網上看了一下,感覺不錯,所以就記錄一下部落格。

1秒殺業務為什麼難做

im系統,例如qq或者微博,每個人都讀自己的資料(好友列表、群列表、個人資訊)。

微博系統,每個人讀你關注的人的資料,乙個人讀多個人的資料。

秒殺系統,庫存只有乙份,所有人會在集中的時間讀和寫這些資料,多個人讀乙個資料。

例如小公尺手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬。又例如12306搶票,票是有限的,庫存乙份,瞬時流量非常多,都讀相同的庫存。讀寫衝突,鎖非常嚴重,這是秒殺業務難的地方。那我們怎麼優化秒殺業務的架構呢?

2

優化方向

優化方向有兩個:

將請求盡量攔截在系統上游(不要讓鎖衝突落到資料庫上去)。傳統秒殺系統之所以掛,請求都壓倒了後端資料層,資料讀寫鎖衝突嚴重,併發高響應慢,幾乎所有請求都超時,流量雖大,下單成功的有效流量甚小。以12306為例,一趟火車其實只有2000張票,200w個人來買,基本沒有人能買成功,請求有效率為0。

充分利用快取,秒殺買票,這是乙個典型的讀多些少的應用場景,大部分請求是車次查詢,票查詢,下單和支付才是寫請求。一趟火車其實只有2000張票,200w個人來買,最多2000個人下單成功,其他人都是查詢庫存,寫比例只有0.1%,讀比例佔99.9%,非常適合使用快取來優化。好,後續講講怎麼個「將請求盡量攔截在系統上游」法,以及怎麼個「快取」法,講講細節。

3

常見秒殺架構

常見的站點架構基本是這樣的(特別是流量上億的站點架構):

瀏覽器端,最上層,會執行到一些js**

站點層,這一層會訪問後端資料,拼html頁面返回給瀏覽器

服務層,向上游遮蔽底層資料細節,提供資料訪問

資料層,最終的庫存是存在這裡的,mysql是乙個典型(當然還有會快取)

這個圖雖然簡單,但能形象的說明大流量高併發的秒殺業務架構,大家要記得這一張圖。

後面細細解析各個層級怎麼優化。

4

各層次優化細節

firebug一抓包,http長啥樣都知道,js是萬萬攔不住程式設計師寫for迴圈,呼叫http介面的,這部分請求怎麼處理?

怎麼攔截?怎麼防止程式設計師寫for迴圈呼叫,有去重依據麼?ip?cookie-id?…想複雜了,這類業務都需要登入,用uid即可。在站點層面,對uid進行請求計數和去重,甚至不需要統一儲存計數,直接站點層記憶體儲存(這樣計數會不准,但最簡單)。乙個uid,5秒只准透過1個請求,這樣又能攔住99%的for迴圈請求。

5s只透過乙個請求,其餘的請求怎麼辦?快取,頁面快取,同乙個uid,限制訪問頻度,做頁面快取,x秒內到達站點層的請求,均返回同一頁面。同乙個item的查詢,例如車次,做頁面快取,x秒內到達站點層的請求,均返回同一頁面。如此限流,既能保證使用者有良好的使用者體驗(沒有返回404)又能保證系統的健壯性(利用頁面快取,把請求攔截在站點層了)。

頁面快取不一定要保證所有站點返回一致的頁面,直接放在每個站點的記憶體也是可以的。優點是簡單,壞處是http請求落到不同的站點,返回的車票資料可能不一樣,這是站點層的請求攔截與快取優化。

好,這個方式攔住了寫for迴圈發http請求的程式設計師,有些高階程式設計師(黑客)控制了10w個肉雞,手裡有10w個uid,同時發請求(先不考慮實名制的問題,小公尺搶手機不需要實名制),這下怎麼辦,站點層按照uid限流攔不住了。

服務層怎麼攔截?大哥,我是服務層,我清楚的知道小公尺只有1萬部手機,我清楚的知道一列火車只有2000張車票,我透10w個請求去資料庫有什麼意義呢?沒錯,請求佇列!

對於寫請求,做請求佇列,每次只透有限的寫請求去資料層(下訂單,支付這樣的寫業務):

如果均成功再放下一批,如果庫存不夠則佇列裡的寫請求全部返回「已售完」。

對於讀請求,怎麼優化?cache抗,不管是memcached還是redis,單機抗個每秒10w應該都是沒什麼問題的。如此限流,只有非常少的寫請求,和非常少的讀快取mis的請求會透到資料層去,又有99.9%的請求被攔住了。

當然,還有業務規則上的一些優化。回想12306所做的,分時分段售票,原來統一10點賣票,現在8點,8點半,9點,...每隔半個小時放出一批:將流量攤勻。

其次,資料粒度的優化:你去購票,對於餘票查詢這個業務,票剩了58張,還是26張,你真的關注麼,其實我們只關心有票和無票?流量大的時候,做乙個粗粒度的 「有票」「無票」快取即可。

第三,一些業務邏輯的非同步:例如 下單業務與 支付業務的分離。這些優化都是結合 業務 來的,我之前分享過乙個觀點「一切脫離業務的架構設計都是耍流氓」架構的優化也要針對業務。

瀏覽器攔截了80%,站點層攔截了99.9%並做了頁面快取,服務層又做了寫請求佇列與資料快取,每次透到資料庫層的請求都是可控的。db基本就沒什麼壓力了,閑庭信步,單機也能扛得住,還是那句話,庫存是有限的,小公尺的產能有限,透這麼多請求來資料庫沒有意義。

全部透到資料庫,100w個下單,0個成功,請求有效率0%。透3k到資料,全部成功,請求有效率100%。

5

總結

上文應該描述的非常清楚了,沒什麼總結了,對於秒殺系統,再次重複下我個人經驗的兩個架構優化思路:

盡量將請求攔截在系統上游(越上游越好);

讀多寫少的常用多使用快取(快取抗讀壓力);

結束語》記得以前玩遊戲,王者榮耀,程咬金太特麼肉了,關鍵是我們團戰竟然先秒殺了程咬金,快笑死我了

秒殺 秒殺系統 優化之路

1 im系統,例如qq或者微博,每個人都讀自己的資料 好友列表 群列表 個人資訊 2 微博系統,每個人讀你關注的人的資料,乙個人讀多個人的資料 3 秒殺系統,庫存只有乙份,所有人會在集中的時間讀和寫這些資料,多個人讀乙個資料。例如 小公尺手機每週二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾...

電商秒殺優化

增加並行數量,就是增大對資料庫的訪問。而這三種優化快取效果排序 頁面快取 url快取 物件快取 jss,js這些內容的優化 首先在goodscontroller中找到商品列表goodlist,資料通過model來傳到good list.html頁面中去 那麼如何取出我們的頁面快取呢?通過下面這句 s...

秒殺系統,庫存優化

直接上 1 public class redisshop 89 autowired 10private productservice productservice 11 autowired 12private stringredistemplate stringredistemplate 13 au...