自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

掌握這些,高并發(fā)秒殺系統(tǒng)就不用擔心了!

開發(fā) 架構 開發(fā)工具
很多小伙伴反饋說,高并發(fā)專題學了那么久,但是,在真正做項目時,仍然不知道如何下手處理高并發(fā)業(yè)務場景!

很多小伙伴反饋說,高并發(fā)專題學了那么久,但是,在真正做項目時,仍然不知道如何下手處理高并發(fā)業(yè)務場景!

[[321895]]

圖片來自 Pexels

甚至很多小伙伴仍然停留在只是簡單的提供接口(CRUD)階段,不知道學習的并發(fā)知識如何運用到實際項目中,就更別提如何構建高并發(fā)系統(tǒng)了!

究竟什么樣的系統(tǒng)算是高并發(fā)系統(tǒng)?今天,我們就一起解密高并發(fā)業(yè)務場景下典型的秒殺系統(tǒng)的架構,結合高并發(fā)專題下的其他文章,學以致用。

電商系統(tǒng)架構

在電商領域,存在著典型的秒殺業(yè)務場景,那何謂秒殺場景呢。簡單的來說就是一件商品的購買人數遠遠大于這件商品的庫存,而且這件商品在很短的時間內就會被搶購一空。

比如每年的 618、雙 11 大促,小米新品促銷等業(yè)務場景,就是典型的秒殺業(yè)務場景。

我們可以將電商系統(tǒng)的架構簡化成下圖所示:

由圖所示,我們可以簡單的將電商系統(tǒng)的核心層分為:負載均衡層、應用層和持久層。

接下來,我們就預估下每一層的并發(fā)量:

  • 假如負載均衡層使用的是高性能的 Nginx,則我們可以預估 Nginx 最大的并發(fā)度為:10W+,這里是以萬為單位。
  • 假設應用層我們使用的是 Tomcat,而 Tomcat 的最大并發(fā)度可以預估為 800 左右,這里是以百為單位。
  • 假設持久層的緩存使用的是 Redis,數據庫使用的是 MySQL,MySQL 的最大并發(fā)度可以預估為 1000 左右,以千為單位。Redis 的最大并發(fā)度可以預估為 5W 左右,以萬為單位。

所以,負載均衡層、應用層和持久層各自的并發(fā)度是不同的,那么,為了提升系統(tǒng)的總體并發(fā)度和緩存,我們通??梢圆扇∧男┓桨改?

①系統(tǒng)擴容

系統(tǒng)擴容包括垂直擴容和水平擴容,增加設備和機器配置,絕大多數的場景有效。

②緩存

本地緩存或者集中式緩存,減少網絡 IO,基于內存讀取數據。大部分場景有效。

③讀寫分離

采用讀寫分離,分而治之,增加機器的并行處理能力。

秒殺系統(tǒng)的特點

對于秒殺系統(tǒng)來說,我們可以從業(yè)務和技術兩個角度來闡述其自身存在的一些特點。

秒殺系統(tǒng)的業(yè)務特點

這里,我們可以使用 12306 網站來舉例,每年春運時,12306 網站的訪問量是非常大的,但是網站平時的訪問量卻是比較平緩的,也就是說,每年春運時節(jié),12306 網站的訪問量會出現瞬時突增的現象。

再比如,小米秒殺系統(tǒng),在上午 10 點開售商品,10 點前的訪問量比較平緩,10 點時同樣會出現并發(fā)量瞬時突增的現象。

所以,秒殺系統(tǒng)的流量和并發(fā)量我們可以使用下圖來表示:

由圖可以看出,秒殺系統(tǒng)的并發(fā)量存在瞬時凸峰的特點,也叫做流量突刺現象。

我們可以將秒殺系統(tǒng)的特點總結如下:

①限時、限量、限價

在規(guī)定的時間內進行;秒殺活動中商品的數量有限;商品的價格會遠遠低于原來的價格,也就是說,在秒殺活動中,商品會以遠遠低于原來的價格出售。

例如,秒殺活動的時間僅限于某天上午 10 點到 10 點半,商品數量只有 10 萬件,售完為止,而且商品的價格非常低,例如:1 元購等業(yè)務場景。

限時、限量和限價可以單獨存在,也可以組合存在。

②活動預熱

需要提前配置活動;活動還未開始時,用戶可以查看活動的相關信息;秒殺活動開始前,對活動進行大力宣傳。

③持續(xù)時間短

購買的人數數量龐大;商品會迅速售完。在系統(tǒng)流量呈現上,就會出現一個突刺現象,此時的并發(fā)訪問量是非常高的,大部分秒殺場景下,商品會在極短的時間內售完。

秒殺系統(tǒng)的技術特點

我們可以將秒殺系統(tǒng)的技術特點總結如下:

①瞬時并發(fā)量非常高

大量用戶會在同一時間搶購商品;瞬間并發(fā)峰值非常高。

②讀多寫少

系統(tǒng)中商品頁的訪問量巨大;商品的可購買數量非常少;庫存的查詢訪問數量遠遠大于商品的購買數量。

在商品頁中往往會加入一些限流措施,例如早期的秒殺系統(tǒng)商品頁會加入驗證碼來平滑前端對系統(tǒng)的訪問流量,近期的秒殺系統(tǒng)商品詳情頁會在用戶打開頁面時,提示用戶登錄系統(tǒng)。這都是對系統(tǒng)的訪問進行限流的一些措施。

③流程簡單

秒殺系統(tǒng)的業(yè)務流程一般比較簡單;總體上來說,秒殺系統(tǒng)的業(yè)務流程可以概括為:下單減庫存。

針對這種短時間內大流量的系統(tǒng)來說,就不太適合使用系統(tǒng)擴容了,因為即使系統(tǒng)擴容了,也就是在很短的時間內會使用到擴容后的系統(tǒng),大部分時間內,系統(tǒng)無需擴容即可正常訪問。

那么,我們可以采取哪些方案來提升系統(tǒng)的秒殺性能呢?

秒殺系統(tǒng)方案

針對秒殺系統(tǒng)的特點,我們可以采取如下的措施來提升系統(tǒng)的性能。

①異步解耦

將整體流程進行拆解,核心流程通過隊列方式進行控制。

②限流防刷

控制網站整體流量,提高請求的門檻,避免系統(tǒng)資源耗盡。

③資源控制

將整體流程中的資源調度進行控制,揚長避短。由于應用層能夠承載的并發(fā)量比緩存的并發(fā)量少很多。

所以,在高并發(fā)系統(tǒng)中,我們可以直接使用 OpenResty 由負載均衡層訪問緩存,避免了調用應用層的性能損耗。

大家可以到 https://openresty.org/cn/ 來了解有關 OpenResty 更多的知識。

同時,由于秒殺系統(tǒng)中,商品數量比較少,我們也可以使用動態(tài)渲染技術,CDN 技術來加速網站的訪問性能。

如果在秒殺活動開始時,并發(fā)量太高時,我們可以將用戶的請求放入隊列中進行處理,并為用戶彈出排隊頁面。

[[321900]]

秒殺系統(tǒng)時序圖

網上很多的秒殺系統(tǒng)和對秒殺系統(tǒng)的解決方案,并不是真正的秒殺系統(tǒng),他們采用的只是同步處理請求的方案,一旦并發(fā)量真的上來了,他們所謂的秒殺系統(tǒng)的性能會急劇下降。我們先來看一下秒殺系統(tǒng)在同步下單時的時序圖。

同步下單流程:

①用戶發(fā)起秒殺請求

在同步下單流程中,首先,用戶發(fā)起秒殺請求。商城服務需要依次執(zhí)行如下流程來處理秒殺請求的業(yè)務。

識別驗證碼是否正確:商城服務判斷用戶發(fā)起秒殺請求時提交的驗證碼是否正確。

判斷活動是否已經結束:驗證當前秒殺活動是否已經結束。

驗證訪問請求是否處于黑名單:在電商領域中,存在著很多的惡意競爭,也就是說,其他商家可能會通過不正當手段來惡意請求秒殺系統(tǒng),占用系統(tǒng)大量的帶寬和其他系統(tǒng)資源。

此時,就需要使用風控系統(tǒng)等實現黑名單機制。為了簡單,也可以使用攔截器統(tǒng)計訪問頻次實現黑名單機制。

驗證真實庫存是否足夠:系統(tǒng)需要驗證商品的真實庫存是否足夠,是否能夠支持本次秒殺活動的商品庫存量。

扣減緩存中的庫存:在秒殺業(yè)務中,往往會將商品庫存等信息存放在緩存中,此時,還需要驗證秒殺活動使用的商品庫存是否足夠,并且需要扣減秒殺活動的商品庫存數量。

計算秒殺的價格:由于在秒殺活動中,商品的秒殺價格和商品的真實價格存在差異,所以,需要計算商品的秒殺價格。

注意:如果在秒殺場景中,系統(tǒng)涉及的業(yè)務更加復雜的話,會涉及更多的業(yè)務操作,這里,我只是列舉出一些常見的業(yè)務操作。

②提交訂單

訂單入口:將用戶提交的訂單信息保存到數據庫中。

扣減真實庫存:訂單入庫后,需要在商品的真實庫存中將本次成功下單的商品數量扣除。

如果我們使用上述流程開發(fā)了一個秒殺系統(tǒng),當用戶發(fā)起秒殺請求時,由于系統(tǒng)每個業(yè)務流程都是串行執(zhí)行的,整體上系統(tǒng)的性能不會太高,當并發(fā)量太高時,我們會為用戶彈出下面的排隊頁面,來提示用戶進行等待。

[[321901]]

此時的排隊時間可能是 15 秒,也可能是 30 秒,甚至是更長時間。這就存在一個問題:在用戶發(fā)起秒殺請求到服務器返回結果的這段時間內,客戶端和服務器之間的連接不會被釋放,這就會占大量占用服務器的資源。

網上很多介紹如何實現秒殺系統(tǒng)的文章都是采用的這種方式,那么,這種方式能做秒殺系統(tǒng)嗎?

答案是可以做,但是這種方式支撐的并發(fā)量并不是太高。此時,有些網友可能會問:我們公司就是這樣做的秒殺系統(tǒng)啊!上線后一直在用,沒啥問題啊!

我想說的是:使用同步下單方式確實可以做秒殺系統(tǒng),但是同步下單的性能不會太高。

之所以你們公司采用同步下單的方式做秒殺系統(tǒng)沒出現大的問題,那是因為你們的秒殺系統(tǒng)的并發(fā)量沒達到一定的量級,也就是說,你們的秒殺系統(tǒng)的并發(fā)量其實并不高。

所以,很多所謂的秒殺系統(tǒng),存在著秒殺的業(yè)務,但是稱不上真正的秒殺系統(tǒng),原因就在于他們使用的是同步的下單流程,限制了系統(tǒng)的并發(fā)流量。

之所以上線后沒出現太大的問題,是因為系統(tǒng)的并發(fā)量不高,不足以壓死整個系統(tǒng)。

如果 12306、淘寶、天貓、京東、小米等大型商城的秒殺系統(tǒng)是這么玩的話,那么,他們的系統(tǒng)遲早會被玩死,他們的系統(tǒng)工程師不被開除才怪!

所以,在秒殺系統(tǒng)中,這種同步處理下單的業(yè)務流程的方案是不可取的。

以上就是同步下單的整個流程操作,如果下單流程更加復雜的話,就會涉及到更多的業(yè)務操作。

異步下單流程:

既然同步下單流程的秒殺系統(tǒng)稱不上真正的秒殺系統(tǒng),那我們就需要采用異步的下單流程了。異步的下單流程不會限制系統(tǒng)的高并發(fā)流量。

①用戶發(fā)起秒殺請求

用戶發(fā)起秒殺請求后,商城服務會經過如下業(yè)務流程。

檢測驗證碼是否正確:用戶發(fā)起秒殺請求時,會將驗證碼一同發(fā)送過來,系統(tǒng)會檢驗驗證碼是否有效,并且是否正確。

是否限流:系統(tǒng)會對用戶的請求進行是否限流的判斷,這里,我們可以通過判斷消息隊列的長度來進行判斷。

因為我們將用戶的請求放在了消息隊列中,消息隊列中堆積的是用戶的請求,我們可以根據當前消息隊列中存在的待處理的請求數量來判斷是否需要對用戶的請求進行限流處理。

例如,在秒殺活動中,我們出售 1000 件商品,此時在消息隊列中存在 1000 個請求,如果后續(xù)仍然有用戶發(fā)起秒殺請求,則后續(xù)的請求我們可以不再處理,直接向用戶返回商品已售完的提示。

所以,使用限流后,我們可以更快的處理用戶的請求和釋放連接的資源。

發(fā)送 MQ:用戶的秒殺請求通過前面的驗證后,我們就可以將用戶的請求參數等信息發(fā)送到 MQ 中進行異步處理,同時,向用戶響應結果信息。

在商城服務中,會有專門的異步任務處理模塊來消費消息隊列中的請求,并處理后續(xù)的異步流程。

在用戶發(fā)起秒殺請求時,異步下單流程比同步下單流程處理的業(yè)務操作更少,它將后續(xù)的操作通過 MQ 發(fā)送給異步處理模塊進行處理,并迅速向用戶返回響應結果,釋放請求連接。

②異步處理

我們可以將下單流程的如下操作進行異步處理:

  • 判斷活動是否已經結束
  • 判斷本次請求是否處于系統(tǒng)黑名單,為了防止電商領域同行的惡意競爭可以為系統(tǒng)增加黑名單機制,將惡意的請求放入系統(tǒng)的黑名單中??梢允褂脭r截器統(tǒng)計訪問頻次來實現。
  • 扣減緩存中的秒殺商品的庫存數量。
  • 生成秒殺 Token,這個 Token 是綁定當前用戶和當前秒殺活動的,只有生成了秒殺 Token 的請求才有資格進行秒殺活動。

這里我們引入了異步處理機制,在異步處理中,系統(tǒng)使用多少資源,分配多少線程來處理相應的任務,是可以進行控制的。

③短輪詢查詢秒殺結果

這里,可以采取客戶端短輪詢查詢是否獲得秒殺資格的方案。例如,客戶端可以每隔 3 秒鐘輪詢請求服務器,查詢是否獲得秒殺資格。

這里,我們在服務器的處理就是判斷當前用戶是否存在秒殺 Token,如果服務器為當前用戶生成了秒殺 Token,則當前用戶存在秒殺資格。

否則繼續(xù)輪詢查詢,直到超時或者服務器返回商品已售完或者無秒殺資格等信息為止。

采用短輪詢查詢秒殺結果時,在頁面上我們同樣可以提示用戶排隊處理中,但是此時客戶端會每隔幾秒輪詢服務器查詢秒殺資格的狀態(tài),相比于同步下單流程來說,無需長時間占用請求連接。

此時,可能會有網友會問:采用短輪詢查詢的方式,會不會存在直到超時也查詢不到是否具有秒殺資格的狀態(tài)呢?

答案是:有可能!這里我們試想一下秒殺的真實場景,商家參加秒殺活動本質上不是為了賺錢,而是提升商品的銷量和商家的知名度,吸引更多的用戶來買自己的商品。

所以,我們不必保證用戶能夠 100% 的查詢到是否具有秒殺資格的狀態(tài)。

④秒殺結算

驗證下單 Token:客戶端提交秒殺結算時,會將秒殺 Token 一同提交到服務器,商城服務會驗證當前的秒殺 Token 是否有效。

加入秒殺購物車:商城服務在驗證秒殺 Token 合法并有效后,會將用戶秒殺的商品添加到秒殺購物車。

⑤提交訂單

訂單入庫:將用戶提交的訂單信息保存到數據庫中。

刪除 Token:秒殺商品訂單入庫成功后,刪除秒殺 Token。

這里大家可以思考一個問題:我們?yōu)槭裁粗辉诋惒较聠瘟鞒痰姆凵糠植捎卯惒教幚恚鴽]有在其他部分采取異步削峰和填谷的措施呢?

這是因為在異步下單流程的設計中,無論是在產品設計上還是在接口設計上,我們在用戶發(fā)起秒殺請求階段對用戶的請求進行了限流操作,可以說,系統(tǒng)的限流操作是非常前置的。

在用戶發(fā)起秒殺請求時進行了限流,系統(tǒng)的高峰流量已經被平滑解決了,再往后走,其實系統(tǒng)的并發(fā)量和系統(tǒng)流量并不是非常高了。

所以,網上很多的文章和帖子中在介紹秒殺系統(tǒng)時,說是在下單時使用異步削峰來進行一些限流操作,那都是在扯淡!

因為下單操作在整個秒殺系統(tǒng)的流程中屬于比較靠后的操作了,限流操作一定要前置處理,在秒殺業(yè)務后面的流程中做限流操作是沒啥卵用的。

高并發(fā)“黑科技”與致勝奇招

假設,在秒殺系統(tǒng)中我們使用 Redis 實現緩存,假設 Redis 的讀寫并發(fā)量在 5 萬左右。

我們的商城秒殺業(yè)務需要支持的并發(fā)量在 100 萬左右。如果這 100 萬的并發(fā)全部打入 Redis 中,Redis 很可能就會掛掉,那么,我們如何解決這個問題呢?

接下來,我們就一起來探討這個問題。在高并發(fā)的秒殺系統(tǒng)中,如果采用 Redis 緩存數據,則 Redis 緩存的并發(fā)處理能力是關鍵,因為很多的前綴操作都需要訪問 Redis。

而異步削峰只是基本的操作,關鍵還是要保證 Redis 的并發(fā)處理能力。

解決這個問題的關鍵思想就是:分而治之,將商品庫存分開放。

暗度陳倉

我們在 Redis 中存儲秒殺商品的庫存數量時,可以將秒殺商品的庫存進行“分割”存儲來提升 Redis 的讀寫并發(fā)量。

例如,原來的秒殺商品的 id 為 10001,庫存為 1000 件,在 Redis 中的存儲為(10001, 1000),我們將原有的庫存分割為 5 份,則每份的庫存為 200 件。

此時,我們在 Redis 中存儲的信息為(10001_0, 200),(10001_1, 200),(10001_2, 200),(10001_3, 200),(10001_4, 200)。

此時,我們將庫存進行分割后,每個分割后的庫存使用商品 id 加上一個數字標識來存儲。

這樣,在對存儲商品庫存的每個 Key 進行 Hash 運算時,得出的 Hash 結果是不同的。

這就說明,存儲商品庫存的 Key 有很大概率不在 Redis 的同一個槽位中,這就能夠提升 Redis 處理請求的性能和并發(fā)量。

分割庫存后,我們還需要在 Redis 中存儲一份商品 id 和分割庫存后的 Key 的映射關系,此時映射關系的 Key 為商品的 id,也就是 10001。

Value 為分割庫存后存儲庫存信息的 Key,也就是 10001_0,10001_1,10001_2,10001_3,10001_4。在 Redis 中我們可以使用 List 來存儲這些值。

在真正處理庫存信息時,我們可以先從 Redis 中查詢出秒殺商品對應的分割庫存后的所有 Key,同時使用 AtomicLong 來記錄當前的請求數量。

使用請求數量對從 Redis 中查詢出的秒殺商品對應的分割庫存后的所有 Key 的長度進行求模運算,得出的結果為 0,1,2,3,4。

再在前面拼接上商品 id 就可以得出真正的庫存緩存的 Key。此時,就可以根據這個 Key 直接到 Redis 中獲取相應的庫存信息。

移花接木

在高并發(fā)業(yè)務場景中,我們可以直接使用 Lua 腳本庫(OpenResty)從負載均衡層直接訪問緩存。

這里,我們思考一個場景:如果在秒殺業(yè)務場景中,秒殺的商品被瞬間搶購一空。

此時,用戶再發(fā)起秒殺請求時,如果系統(tǒng)由負載均衡層請求應用層的各個服務,再由應用層的各個服務訪問緩存和數據庫。

其實,本質上已經沒有任何意義了,因為商品已經賣完了,再通過系統(tǒng)的應用層進行層層校驗已經沒有太多意義了!!

而應用層的并發(fā)訪問量是以百為單位的,這又在一定程度上會降低系統(tǒng)的并發(fā)度。

為了解決這個問題,此時,我們可以在系統(tǒng)的負載均衡層取出用戶發(fā)送請求時攜帶的用戶 id,商品 id 和秒殺活動 id 等信息,直接通過 Lua 腳本等技術來訪問緩存中的庫存信息。

如果秒殺商品的庫存小于或者等于 0,則直接返回用戶商品已售完的提示信息,而不用再經過應用層的層層校驗了。

針對這個架構,我們可以參見本文中的電商系統(tǒng)的架構圖(正文開始的第一張圖)。

寫在最后

最后,附上并發(fā)編程需要掌握的核心技能知識圖,祝大家在學習并發(fā)編程時,少走彎路。

后記:記住你比別人強的地方,不是你做過多少年的 CRUD 工作,而是你比別人掌握了更多深入的技能。

不要總停留在 CRUD 的表面工作,理解并掌握底層原理并熟悉源碼實現,并形成自己的抽象思維能力,做到靈活運用,才是你突破瓶頸,脫穎而出的重要方向!

你在刷抖音,玩游戲的時候,別人都在這里學習,成長,提升,人與人最大的差距其實就是思維。你可能不信,優(yōu)秀的人,總是在一起。。

作者:冰河技術

編輯:陶家龍

出處:轉載自微信公眾號冰河技術(hacker-binghe)

 

責任編輯:武曉燕 來源: 冰河技術
相關推薦

2018-09-15 04:59:01

2025-02-20 00:01:00

2020-10-14 07:20:53

高并發(fā)

2015-05-29 09:01:48

2020-04-30 09:19:56

Docker容器虛擬機

2024-07-03 11:01:55

2021-12-21 09:05:46

命令Linux敲錯

2016-08-09 16:17:37

高德地圖TFBOYS大數據

2021-08-26 08:24:33

高并發(fā)秒殺系統(tǒng)

2020-06-15 08:03:17

大文件OOM內存

2025-01-20 00:00:03

高并發(fā)秒殺業(yè)務

2023-11-27 18:07:05

Go并發(fā)編程

2019-10-30 16:54:08

golangredis數據庫

2019-09-04 10:00:07

手機人臉識別

2021-06-23 06:48:42

秒殺Java電商

2021-08-13 22:38:36

大數據互聯網技術

2020-11-09 07:25:20

函數 JavaScript數據

2024-08-01 11:38:40

2015-10-22 10:38:43

Wi-Fi燃氣報警器
點贊
收藏

51CTO技術棧公眾號