如何解決高并發,秒殺問題

相信不少人會被這個問題困擾,分享大家一篇這樣的文章,希望能夠幫到你!

一、秒殺業務為什么難做?
1)im系統,例如qq或者微博,每個人都讀自己的數據(好友列表、群列表、個人信息);
2)微博系統,每個人讀你關注的人的數據,一個人讀多個人的數據;
3)秒殺系統,庫存只有一份,所有人會在集中的時間讀和寫這些數據,多個人讀一個數據。

例如:小米手機每周二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬。

又例如:12306搶票,票是有限的,庫存一份,瞬時流量非常多,都讀相同的庫存。讀寫沖突,鎖非常嚴重,這是秒殺業務難的地方。那我們怎么優化秒殺業務的架構呢?

二、優化方向
優化方向有兩個(今天就講這兩個點):

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

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

三、常見秒殺架構
常見的站點架構基本是這樣的(絕對不畫忽悠類的架構圖)
圖片描述

(1)瀏覽器端,最上層,會執行到一些JS代碼
(2)站點層,這一層會訪問后端數據,拼html頁面返回給瀏覽器
(3)服務層,向上游屏蔽底層數據細節,提供數據訪問
(4)數據層,最終的庫存是存在這里的,mysql是一個典型(當然還有會緩存)

這個圖雖然簡單,但能形象的說明大流量高并發的秒殺業務架構,大家要記得這一張圖。后面細細解析各個層級怎么優化。

四、各層次優化細節
第一層,客戶端怎么優化(瀏覽器層,APP層)

問大家一個問題,大家都玩過微信的搖一搖搶紅包對吧,每次搖一搖,就會往后端發送請求么?回顧我們下單搶票的場景,點擊了“查詢”按鈕之后,系統那個卡呀,進度條漲的慢呀,作為用戶,我會不自覺的再去點擊“查詢”,對么?繼續點,繼續點,點點點。。。有用么?平白無故的增加了系統負載,一個用戶點5次,80%的請求是這么多出來的,怎么整?

(a)產品層面,用戶點擊“查詢”或者“購票”后,按鈕置灰,禁止用戶重復提交請求;

(b)JS層面,限制用戶在x秒之內只能提交一次請求;

APP層面,可以做類似的事情,雖然你瘋狂的在搖微信,其實x秒才向后端發起一次請求。這就是所謂的“將請求盡量攔截在系統上游”,越上游越好,瀏覽器層,APP層就給攔住,這樣就能擋住80%+的請求,這種辦法只能攔住普通用戶(但99%的用戶是普通用戶)對于群內的高端程序員是攔不住的。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個請求去數據庫有什么意義呢?沒錯,請求隊列!

對于寫請求,做請求隊列,每次只透有限的寫請求去數據層(下訂單,支付這樣的寫業務)

1w部手機,只透1w個下單請求去db

3k張火車票,只透3k個下單請求去db

如果均成功再放下一批,如果庫存不夠則隊列里的寫請求全部返回“已售完”。

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

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

其次,數據粒度的優化:你去購票,對于余票查詢這個業務,票剩了58張,還是26張,你真的關注么,其實我們只關心有票和無票?流量大的時候,做一個粗粒度的“有票”“無票”緩存即可。

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

第四層 最后是數據庫層

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

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

五、總結
上文應該描述的非常清楚了,沒什么總結了,對于秒殺系統,再次重復下我個人經驗的兩個架構優化思路:
(1)盡量將請求攔截在系統上游(越上游越好);

(2)讀多寫少的常用多使用緩存(緩存抗讀壓力);

瀏覽器和APP:做限速

站點層:按照uid做限速,做頁面緩存

服務層:按照業務做寫請求隊列控制流量,做數據緩存

數據層:閑庭信步

并且:結合業務做優化

六、Q&A
問題1、按你的架構,其實壓力最大的反而是站點層,假設真實有效的請求數有1000萬,不太可能限制請求連接數吧,那么這部分的壓力怎么處理?

答:每秒鐘的并發可能沒有1kw,假設有1kw,解決方案2個:

(1)站點層是可以通過加機器擴容的,最不濟1k臺機器來唄。
(2)如果機器不夠,拋棄請求,拋棄50%(50%直接返回稍后再試),原則是要保護系統,不能讓所有用戶都失敗。

問題2、“控制了10w個肉雞,手里有10w個uid,同時發請求” 這個問題怎么解決哈?

答:上面說了,服務層寫請求隊列控制

問題3:限制訪問頻次的緩存,是否也可以用于搜索?例如A用戶搜索了“手機”,B用戶搜索“手機”,優先使用A搜索后生成的緩存頁面?

答:這個是可以的,這個方法也經常用在“動態”運營活動頁,例如短時間推送4kw用戶app-push運營活動,做頁面緩存。

問題4:如果隊列處理失敗,如何處理?肉雞把隊列被撐爆了怎么辦?

答:處理失敗返回下單失敗,讓用戶再試。隊列成本很低,爆了很難吧。最壞的情況下,緩存了若干請求之后,后續請求都直接返回“無票”(隊列里已經有100w請求了,都等著,再接受請求也沒有意義了)

問題5:站點層過濾的話,是把uid請求數單獨保存到各個站點的內存中么?如果是這樣的話,怎么處理多臺服務器集群經過負載均衡器將相同用戶的響應分布到不同服務器的情況呢?還是說將站點層的過濾放到負載均衡前?

答:可以放在內存,這樣的話看似一臺服務器限制了5s一個請求,全局來說(假設有10臺機器),其實是限制了5s 10個請求,解決辦法:

1)加大限制(這是建議的方案,最簡單)
2)在nginx層做7層均衡,讓一個uid的請求盡量落到同一個機器上

問題6:服務層過濾的話,隊列是服務層統一的一個隊列?還是每個提供服務的服務器各一個隊列?如果是統一的一個隊列的話,需不需要在各個服務器提交的請求入隊列前進行鎖控制?

答:可以不用統一一個隊列,這樣的話每個服務透過更少量的請求(總票數/服務個數),這樣簡單。統一一個隊列又復雜了。

問題7:秒殺之后的支付完成,以及未支付取消占位,如何對剩余庫存做及時的控制更新?

答:數據庫里一個狀態,未支付。如果超過時間,例如45分鐘,庫存會重新會恢復(大家熟知的“回倉”),給我們搶票的啟示是,開動秒殺后,45分鐘之后再試試看,說不定又有票喲~

問題8:不同的用戶瀏覽同一個商品 落在不同的緩存實例顯示的庫存完全不一樣 請問老師怎么做緩存數據一致或者是允許臟讀?

答:目前的架構設計,請求落到不同的站點上,數據可能不一致(頁面緩存不一樣),這個業務場景能接受。但數據庫層面真實數據是沒問題的。

問題9:就算處于業務把優化考慮“3k張火車票,只透3k個下單請求去db”那這3K個訂單就不會發生擁堵了嗎?

答:(1)數據庫抗3k個寫請求還是ok的;(2)可以數據拆分;(3)如果3k扛不住,服務層可以控制透過去的并發數量,根據壓測情況來吧,3k只是舉例;

問題10;如果在站點層或者服務層處理后臺失敗的話,需不需要考慮對這批處理失敗的請求做重放?還是就直接丟棄?

答:別重放了,返回用戶查詢失敗或者下單失敗吧,架構設計原則之一是“fail fast”。

問題11.對于大型系統的秒殺,比如12306,同時進行的秒殺活動很多,如何分流?

答:垂直拆分

問題12、額外又想到一個問題。這套流程做成同步還是異步的?如果是同步的話,應該還存在會有響應反饋慢的情況。但如果是異步的話,如何控制能夠將響應結果返回正確的請求方?

答:用戶層面肯定是同步的(用戶的http請求是夯住的),服務層面可以同步可以異步。

問題13、秒殺群提問:減庫存是在那個階段減呢?如果是下單鎖庫存的話,大量惡意用戶下單鎖庫存而不支付如何處理呢?

答:數據庫層面寫請求量很低,還好,下單不支付,等時間過完再“回倉”,之前提過了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280124.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280124.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280124.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring原理之代理與動態代理模式總結(四)

2019獨角獸企業重金招聘Python工程師標準>>> 代理模式 1,什么是代理模式? 代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。2,代理模式有什么好處? 在某些情況下,一個客戶不…

可執行文件添加快捷方式_如何停止Windows向快捷方式文件名添加“-快捷方式”...

可執行文件添加快捷方式When you make a new shortcut in Windows, it automatically adds “- Shortcut” to the end of the shortcut’s file name. This doesn’t seem like a big deal, but they can be bothersome. Sure, you can remove the text yourself when you cre…

Red hat6.4重新安裝yum

今天在Red Hat上安裝軟件時,發現需要依賴軟件,然而在用yum指令時,出現了下面的錯誤: This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. 出現這個問題的原因是&…

使用 BenchmarkDotNet 比較指定容量的 List 的性能

我們之前提到 List 是 .NET 中常用的數據結構,其在存儲大量數據時,如果能夠指定它的初始化容量,就會有性能提升。這個優化的方法并不是很明顯,因此本文將使用 BenchmarkDotNet 庫,通過定量對比的方式來證明這一點。實驗…

看明星合影爭C位,學PPT中C位排版法

在娛樂圈里,C位是大咖位,是對藝人實力的最好證明,藝人們自然會想著去力爭C位,正所謂“不想當將軍的兵不是好兵,不想站C位的明星不是好明星”。那么,C位是什么意思?C位,網絡流行語&am…

javafx由淺到深的 認識(一)

javafx是一款比較新興的語言框架,隨著javafx越來越實用,估計許多程序員也會慢慢接觸它,故我在這里對它由淺到深進行介紹一下. 首先,要了解javafx,就應該先知道.xml文件的布局軟件,以往java都是通過敲代碼來進行布局的,但javafx有力新的突破,它實現了拖動方式,目前我使用的輔助軟…

linux用戶的根目錄_為什么Linux允許用戶刪除根目錄?

linux用戶的根目錄Most of the time, none of us willingly performs an action that will literally break our operating systems and force us to reinstall them. But what if such an action could easily occur even by accident on the user’s part? Today’s SuperUs…

純css實現叉號

HMTL部分 <a href"#" class"close"></a> CSS部分 .close {position: absolute;right: 32px;top: 32px;width: 32px;height: 32px; } .close:before, .close:after {position: absolute;left: 15px;content: ;height: 33px;width: 2px;backgro…

微軟跨平臺maui開發chatgpt客戶端

image什么是maui.NET 多平臺應用 UI (.NET MAUI) 是一個跨平臺框架&#xff0c;用于使用 C# 和 XAML 創建本機移動(ios,andriod)和桌面(windows,mac)應用。imagechagpt最近這玩意很火&#xff0c;由于網頁版本限制了ip&#xff0c;還得必須開代理&#xff0c; 用起來比較麻煩&a…

在Xshell 6開NumLock時按小鍵盤上的數字鍵并不能輸入數字

小鍵盤問題 在Xshell 6上用vi的時候&#xff0c;開NumLock時按小鍵盤上的數字鍵并不能輸入數字&#xff0c;而是出現一個字母然后換行&#xff08;實際上是命令模式上對應上下左右的鍵&#xff09;。解決方法 選項Terminal->Features里&#xff0c;找到Disable application …

WebP 在減少圖片體積和流量上的效果如何?—— WebP 技術實踐分享

作者 | Jackson編輯 | 尾尾 不論是 PC 還是移動端&#xff0c;圖片一直占據著頁面流量的大頭&#xff0c;在圖片的大小和質量之間如何權衡&#xff0c;成為了長期困擾開發者們的問題。而 WebP 技術的出現&#xff0c;為解決該問題提供了好的方案。本文將為大家詳細介紹 WebP 技…

chrome 固定縮放比例_您如何調整Google Chrome瀏覽器的用戶界面縮放比例?

chrome 固定縮放比例Everything can be going along nicely until a program gets a new update that suddenly turns everything into a visual mess, like scaling up the UI, for example. Is there a simple solution? Today’s SuperUser Q&A post has some helpful …

樹莓派 Raspberry Pi 更換國內源

http://www.shumeipaiba.com/wanpai/jiaocheng/16.html轉載于:https://www.cnblogs.com/Baronboy/p/9185849.html

優雅告別 2022 年,2023 年主題:敢想,就敢做!

自從工作之后&#xff0c;每年春節我都會花一天時間&#xff0c;一個人待在一個小房間&#xff0c;思考自己今年做了什么具備階段性成果的事情。然后&#xff0c;寫下明年需要執行的計劃。會寫在一個 XMind 文件里&#xff0c;記錄每一年將要執行的計劃&#xff0c;且未完成的計…

純js上傳文件 很好用

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>參數設置</title> <meta name"keywords&q…

買臺電腦,不行!去旅游一下,不行!論程序員怎么實現財務自由!

“最近讀了一本不是編程的程序員技能書《軟技能-代碼之外的生存指南》&#xff0c;全書分為 7 個篇章&#xff0c;分別是職業、自我營銷、學習、生產力、理財、健身和精神。在讀完職業、自我營銷和理財這三個篇章后&#xff0c;讓我感觸很深&#xff0c;也讓我很意外。本來以為…

java發送gmail_如何在Gmail中輕松通過電子郵件發送人群

java發送gmailMailing lists are an old tool in the email arsenal, but their implementation in Gmail isn’t immediately intuitive. Read on as we show you how to email groups using your Gmail account. 郵件列表是電子郵件庫中的一個舊工具&#xff0c;但是在Gmail中…

移動web開發相關筆記(三)

1.推薦以sublime插件的排名官網:https://packagecontrol.io/&#xff08;sublime插件官網&#xff09;2.時間算法【//總秒數var totalSecond 3671;//獲取里面的小時var hoursMath.floor(totalSecond/3600);//獲取剩下的分鐘var minuteMath.floor(totalSecond%3600/60);//獲取剩…

互聯網和IT行業越來越嚴峻,前景幾何?

楔子新冠疫情反反復復&#xff0c;互聯網和IT行業一路下滑。硅谷裁員高達10萬人。前景該何處何從呢&#xff1f;春江水暖豬先知IT行業如此的不景氣&#xff0c;自然是一些在風口上被吹起來的豬首先感受到了。他們進行的自救其實就一條:裁員&#xff0c;大量的裁員。裁員可以解決…

Asp.net MVC使用Model Binding解除Session, Cookie等依賴

上篇文章"Asp.net MVC使用Filter解除Session, Cookie等依賴"介紹了如何使用Filter來解除對于Session, Cookie的依賴。其實這個也可以通過Model Binding來達到同樣的效果。 什么是Model Binding? Model Binding的作用就是將Request請求中包含的散亂參數&#xff0c;根…