秒殺系統(tǒng)流量削峰這事兒應(yīng)該怎么做娇跟?

如果你看過秒殺系統(tǒng)的流量監(jiān)控圖的話岩齿,你會發(fā)現(xiàn)它是一條直線,就在秒殺開始那一秒是一條很直很直的線苞俘,這是因?yàn)槊霘⒄埱笤跁r間上高度集中于某一特定的時間點(diǎn)纯衍。這樣一來,就會導(dǎo)致一個特別高的流量峰值苗胀,它對資源的消耗是瞬時的襟诸。

但是對秒殺這個場景來說,最終能夠搶到商品的人數(shù)是固定的基协,也就是說100人和10000人發(fā)起請求的結(jié)果都是一樣的歌亲,并發(fā)度越高,無效請求也越多澜驮。

但是從業(yè)務(wù)上來說陷揪,秒殺活動是希望更多的人來參與的,也就是開始之前希望有更多的人來刷頁面,但是真正開始下單時悍缠,秒殺請求并不是越多越好卦绣。因此我們可以設(shè)計(jì)一些規(guī)則,讓并發(fā)的請求更多地延緩飞蚓,而且我們甚至可以過濾掉一些無效請求滤港。

為什么要削峰

為什么要削峰呢?或者說峰值會帶來哪些壞處趴拧?

我們知道服務(wù)器的處理資源是恒定的溅漾,你用或者不用它的處理能力都是一樣的,所以出現(xiàn)峰值的話著榴,很容易導(dǎo)致忙到處理不過來添履,閑的時候卻又沒有什么要處理。但是由于要保證服務(wù)質(zhì)量脑又,我們的很多處理資源只能按照忙的時候來預(yù)估暮胧,而這會導(dǎo)致資源的一個浪費(fèi)。

這就好比因?yàn)榇嬖谠绺叻搴屯砀叻宓膯栴}问麸,所以有了錯峰限行的解決方案叔壤。

削峰的存在,一是可以讓服務(wù)端處理變得更加平穩(wěn)口叙,二是可以節(jié)省服務(wù)器的資源成本炼绘。

針對秒殺這一場景,削峰從本質(zhì)上來說就是更多地延緩用戶請求的發(fā)出妄田,以便減少和過濾掉一些無效請求俺亮,它遵從“請求數(shù)要盡量少”的原則。

今天疟呐,我就來介紹一下流量削峰的一些操作思路:排隊(duì)脚曾、答題、分層過濾启具。

這幾種方式都是無損(即不會損失用戶的發(fā)出請求)的實(shí)現(xiàn)方案本讥,當(dāng)然還有些有損的實(shí)現(xiàn)方案,包括我們后面要介紹的關(guān)于穩(wěn)定性的一些辦法鲁冯,比如限流和機(jī)器負(fù)載保護(hù)等一些強(qiáng)制措施也能達(dá)到削峰保護(hù)的目的拷沸,當(dāng)然這都是不得已的一些措施,因此就不歸類到這里了薯演。

排隊(duì)

要對流量進(jìn)行削峰撞芍,最容易想到的解決方案就是用消息隊(duì)列來緩沖瞬時流量,把同步的直接調(diào)用轉(zhuǎn)換成異步的間接推送跨扮,中間通過一個隊(duì)列在一端承接瞬時的流量洪峰序无,在另一端平滑地將消息推送出去验毡。在這里,消息隊(duì)列就像“水庫”一樣帝嗡,攔蓄上游的洪水晶通,削減進(jìn)入下游河道的洪峰流量,從而達(dá)到減免洪水災(zāi)害的目的哟玷。

用消息隊(duì)列來緩沖瞬時流量的方案狮辽,如下圖所示:

l消息隊(duì)列來緩沖瞬時流量

但是,如果流量峰值持續(xù)一段時間達(dá)到了消息隊(duì)列的處理上限碗降,例如本機(jī)的消息積壓達(dá)到了存儲空間的上限隘竭,消息隊(duì)列同樣也會被壓垮塘秦,這樣雖然保護(hù)了下游的系統(tǒng)讼渊,但是和直接把請求丟棄也沒多大的區(qū)別爪幻。就像遇到洪水爆發(fā)時,即使是有水庫恐怕也無濟(jì)于事。

除了消息隊(duì)列,類似的排隊(duì)方式還有很多钉赁,例如:

利用線程池加鎖等待也是一種常用的排隊(duì)方式;

先進(jìn)先出、先進(jìn)后出等常用的內(nèi)存排隊(duì)算法的實(shí)現(xiàn)方式钱慢;

把請求序列化到文件中,然后再順序地讀文件(例如基于MySQL binlog的同步機(jī)制)來恢復(fù)請求等方式策严。

可以看到怀各,這些方式都有一個共同特征寿酌,就是把“一步的操作”變成“兩步的操作”法焰,其中增加的一步操作用來起到緩沖的作用。

說到這里你可能會說颁股,這樣一來增加了訪問請求的路徑啊,并不符合我們介紹的“4要1不要”原則梧疲。沒錯胁澳,的確看起來不太合理宇智,但是如果不增加一個緩沖步驟喂分,那么在一些場景下系統(tǒng)很可能會直接崩潰萝嘁,所以最終還是需要你做出妥協(xié)和平衡。

答題

你是否還記得钝鸽,最早期的秒殺只是純粹地刷新頁面和點(diǎn)擊購買按鈕汇恤,它是后來才增加了答題功能的庞钢。那么,為什么要增加答題功能呢因谎?

這主要是為了增加購買的復(fù)雜度基括,從而達(dá)到兩個目的。

第一個目的是防止部分買家使用秒殺器在參加秒殺時作弊财岔。2011年秒殺非撤缑螅火的時候,秒殺器也比較猖獗匠璧,因而沒有達(dá)到全民參與和營銷的目的桐款,所以系統(tǒng)增加了答題來限制秒殺器。增加答題后夷恍,下單的時間基本控制在2s后魔眨,秒殺器的下單比例也大大下降。答題頁面如下圖所示酿雪。

答題頁面

第二個目的其實(shí)就是延緩請求遏暴,起到對請求流量進(jìn)行削峰的作用,從而讓系統(tǒng)能夠更好地支持瞬時的流量高峰指黎。這個重要的功能就是把峰值的下單請求拉長朋凉,從以前的1s之內(nèi)延長到2s~10s。這樣一來醋安,請求峰值基于時間分片了杂彭。這個時間的分片對服務(wù)端處理并發(fā)非常重要墓毒,會大大減輕壓力。

而且亲怠,由于請求具有先后順序蚁鳖,靠后的請求到來時自然也就沒有庫存了,因此根本到不了最后的下單步驟赁炎,所以真正的并發(fā)寫就非常有限了醉箕。這種設(shè)計(jì)思路目前用得非常普遍,如當(dāng)年支付寶的“咻一咻”徙垫、微信的“搖一搖”都是類似的方式讥裤。

這里,我重點(diǎn)說一下秒殺答題的設(shè)計(jì)思路姻报。

秒殺答題

如上圖所示己英,整個秒殺答題的邏輯主要分為3部分。

題庫生成模塊吴旋,這個部分主要就是生成一個個問題和答案损肛,其實(shí)題目和答案本身并不需要很復(fù)雜,重要的是能夠防止由機(jī)器來算出結(jié)果荣瑟,即防止秒殺器來答題治拿。

題庫的推送模塊,用于在秒殺答題前笆焰,把題目提前推送給詳情系統(tǒng)和交易系統(tǒng)劫谅。題庫的推送主要是為了保證每次用戶請求的題目是唯一的,目的也是防止答題作弊嚷掠。

題目的圖片生成模塊捏检,用于把題目生成為圖片格式,并且在圖片里增加一些干擾因素不皆。這也同樣是為防止機(jī)器直接來答題贯城,它要求只有人才能理解題目本身的含義。這里還要注意一點(diǎn)霹娄,由于答題時網(wǎng)絡(luò)比較擁擠能犯,我們應(yīng)該把題目的圖片提前推送到CDN上并且要進(jìn)行預(yù)熱,不然的話當(dāng)用戶真正請求題目時项棠,圖片可能加載比較慢悲雳,從而影響答題的體驗(yàn)。

其實(shí)真正答題的邏輯比較簡單香追,很好理解:當(dāng)用戶提交的答案和題目對應(yīng)的答案做比較合瓢,如果通過了就繼續(xù)進(jìn)行下一步的下單邏輯,否則就失敗透典。

我們可以把問題和答案用下面這樣的key來進(jìn)行MD5加密:

問題key:userId+itemId+question_Id+time+PK

答案key:userId+itemId+answer+PK

驗(yàn)證的邏輯如下圖所示:

答題的驗(yàn)證邏輯

注意晴楔,這里面的驗(yàn)證邏輯顿苇,除了驗(yàn)證問題的答案以外,還包括用戶本身身份的驗(yàn)證税弃,例如是否已經(jīng)登錄纪岁、用戶的Cookie是否完整、用戶是否重復(fù)頻繁提交等则果。

除了做正確性驗(yàn)證幔翰,我們還可以對提交答案的時間做些限制,例如從開始答題到接受答案要超過1s西壮,因?yàn)樾∮?s是人為操作的可能性很小遗增,這樣也能防止機(jī)器答題的情況。

分層過濾

前面介紹的排隊(duì)和答題要么是少發(fā)請求款青,要么對發(fā)出來的請求進(jìn)行緩沖做修,而針對秒殺場景還有一種方法,就是對請求進(jìn)行分層過濾抡草,從而過濾掉一些無效的請求饰及。分層過濾其實(shí)就是采用“漏斗”式設(shè)計(jì)來處理請求的,如下圖所示康震。

假如請求分別經(jīng)過CDN燎含、前臺讀系統(tǒng)(如商品詳情系統(tǒng))、后臺系統(tǒng)(如交易系統(tǒng))和數(shù)據(jù)庫這幾層签杈,那么:

大部分?jǐn)?shù)據(jù)和流量在用戶瀏覽器或者CDN上獲取瘫镇,這一層可以攔截大部分?jǐn)?shù)據(jù)的讀榷κ蕖答姥;

經(jīng)過第二層(即前臺系統(tǒng))時數(shù)據(jù)(包括強(qiáng)一致性的數(shù)據(jù))盡量得走Cache,過濾一些無效的請求谚咬;

再到第三層后臺系統(tǒng)鹦付,主要做數(shù)據(jù)的二次檢驗(yàn),對系統(tǒng)做好保護(hù)和限流择卦,這樣數(shù)據(jù)量和請求就進(jìn)一步減少敲长;

最后在數(shù)據(jù)層完成數(shù)據(jù)的強(qiáng)一致性校驗(yàn)。

這樣就像漏斗一樣秉继,盡量把數(shù)據(jù)量和請求量一層一層地過濾和減少了祈噪。

分層過濾的核心思想是:在不同的層次盡可能地過濾掉無效請求,讓“漏斗”最末端的才是有效請求尚辑。而要達(dá)到這種效果辑鲤,我們就必須對數(shù)據(jù)做分層的校驗(yàn)。

分層校驗(yàn)的基本原則是:

將動態(tài)請求的讀數(shù)據(jù)緩存(Cache)在Web端杠茬,過濾掉無效的數(shù)據(jù)讀月褥;

對讀數(shù)據(jù)不做強(qiáng)一致性校驗(yàn)弛随,減少因?yàn)橐恢滦孕r?yàn)產(chǎn)生瓶頸的問題;

對寫數(shù)據(jù)進(jìn)行基于時間的合理分片宁赤,過濾掉過期的失效請求舀透;

對寫請求做限流保護(hù),將超出系統(tǒng)承載能力的請求過濾掉决左;

對寫數(shù)據(jù)進(jìn)行強(qiáng)一致性校驗(yàn)愕够,只保留最后有效的數(shù)據(jù)。

分層校驗(yàn)的目的是:

在讀系統(tǒng)中佛猛,盡量減少由于一致性校驗(yàn)帶來的系統(tǒng)瓶頸链烈,但是盡量將不影響性能的檢查條件提前,如用戶是否具有秒殺資格挚躯、商品狀態(tài)是否正常强衡、用戶答題是否正確、秒殺是否已經(jīng)結(jié)束码荔、是否非法請求漩勤、營銷等價物是否充足等;

在寫數(shù)據(jù)系統(tǒng)中缩搅,主要對寫的數(shù)據(jù)(如“庫存”)做一致性檢查越败,最后在數(shù)據(jù)庫層保證數(shù)據(jù)的最終準(zhǔn)確性(如“庫存”不能減為負(fù)數(shù))。

總結(jié)一下

今天硼瓣,我介紹了如何在網(wǎng)站面臨大流量沖擊時進(jìn)行請求的削峰究飞,并主要介紹了削峰的3種處理方式:

一個是通過隊(duì)列來緩沖請求,即控制請求的發(fā)出堂鲤;

一個是通過答題來延長請求發(fā)出的時間亿傅,在請求發(fā)出后承接請求時進(jìn)行控制,最后再對不符合條件的請求進(jìn)行過濾瘟栖;

最后一種是對請求進(jìn)行分層過濾葵擎。

其中,隊(duì)列緩沖方式更加通用半哟,它適用于內(nèi)部上下游系統(tǒng)之間調(diào)用請求不平緩的場景酬滤,由于內(nèi)部系統(tǒng)的服務(wù)質(zhì)量要求不能隨意丟棄請求,所以使用消息隊(duì)列能起到很好的削峰和緩沖作用寓涨。

而答題更適用于秒殺或者營銷活動等應(yīng)用場景盯串,在請求發(fā)起端就控制發(fā)起請求的速度,因?yàn)樵降胶竺鏌o效請求也會越多戒良,所以配合后面介紹的分層攔截的方式体捏,可以更進(jìn)一步減少無效請求對系統(tǒng)資源的消耗。

分層過濾非常適合交易性的寫請求,比如減庫存或者拼車這種場景译打,在讀的時候需要知道還有沒有庫存或者是否還有剩余空座位耗拓。但是由于庫存和座位又是不停變化的,所以讀的數(shù)據(jù)是否一定要非常準(zhǔn)確呢奏司?其實(shí)不一定乔询,你可以放一些請求過去,然后在真正減的時候再做強(qiáng)一致性保證韵洋,這樣既過濾一些請求又解決了強(qiáng)一致性讀的瓶頸竿刁。

不過,在削峰的處理方式上除了采用技術(shù)手段搪缨,其實(shí)還可以采用業(yè)務(wù)手段來達(dá)到一定效果食拜,例如在零點(diǎn)開啟大促的時候由于流量太大導(dǎo)致支付系統(tǒng)阻塞,這個時候可以采用發(fā)放優(yōu)惠券副编、發(fā)起抽獎活動等方式负甸,將一部分流量分散到其他地方,這樣也能起到緩沖流量的作用痹届。

如果想學(xué)習(xí)Java工程化呻待、高性能及分布式、深入淺出队腐。微服務(wù)蚕捉、Spring,MyBatis柴淘,Netty源碼分析的朋友可以加我的Java高級交流:787707172迫淹,群里有阿里大牛直播講解技術(shù),以及Java大型互聯(lián)網(wǎng)技術(shù)的視頻免費(fèi)分享給大家为严。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敛熬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梗脾,更是在濱河造成了極大的恐慌荸型,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炸茧,死亡現(xiàn)場離奇詭異,居然都是意外死亡稿静,警方通過查閱死者的電腦和手機(jī)梭冠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來改备,“玉大人控漠,你說我怎么就攤上這事。” “怎么了盐捷?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵偶翅,是天一觀的道長。 經(jīng)常有香客問我碉渡,道長聚谁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任滞诺,我火速辦了婚禮形导,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘习霹。我一直安慰自己朵耕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布淋叶。 她就那樣靜靜地躺著阎曹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪煞檩。 梳的紋絲不亂的頭發(fā)上芬膝,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機(jī)與錄音形娇,去河邊找鬼锰霜。 笑死,一個胖子當(dāng)著我的面吹牛桐早,可吹牛的內(nèi)容都是我干的癣缅。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼哄酝,長吁一口氣:“原來是場噩夢啊……” “哼友存!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陶衅,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤屡立,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搀军,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膨俐,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年罩句,在試婚紗的時候發(fā)現(xiàn)自己被綠了焚刺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡门烂,死狀恐怖乳愉,靈堂內(nèi)的尸體忽然破棺而出兄淫,到底是詐尸還是另有隱情,我是刑警寧澤蔓姚,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布捕虽,位于F島的核電站,受9級特大地震影響坡脐,放射性物質(zhì)發(fā)生泄漏泄私。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一挨措、第九天 我趴在偏房一處隱蔽的房頂上張望挖滤。 院中可真熱鬧,春花似錦浅役、人聲如沸斩松。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惧盹。三九已至,卻和暖如春瞪讼,著一層夾襖步出監(jiān)牢的瞬間钧椰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工符欠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嫡霞,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓希柿,卻偏偏與公主長得像诊沪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子曾撤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容