下午。
羅晟依然待在藍(lán)星科技集團(tuán),本來(lái)今天下午他要去蔚藍(lán)海岸實(shí)驗(yàn)室主持一個(gè)技術(shù)會(huì)議的,不過(guò)在得知國(guó)家鐵路集團(tuán)前來(lái)尋求技術(shù)支持幫助,他臨時(shí)修改了一下自己的工作安排,選擇優(yōu)先接見(jiàn)劉副總。
主要是年關(guān)將近,全國(guó)各地的民眾尤其是外出務(wù)工的農(nóng)民工都急著趕回家過(guò)年,這個(gè)群體非常不容易,羅晟覺(jué)得自己能為他們做點(diǎn)什么就做點(diǎn)什么,別的不說(shuō)幫助他們更輕松的買(mǎi)到一張回家過(guò)年團(tuán)聚的車(chē)票也是一件很有意義的事情。
況且還能收獲一位大客戶(hù)。
……
此時(shí)此刻,公司的一間會(huì)客室里,羅晟與劉副總等七八個(gè)國(guó)家鐵路集團(tuán)的人在一塊。
簡(jiǎn)單見(jiàn)面寒暄了幾句,劉副總找到重點(diǎn)話題的切入口,說(shuō)道:“12306票務(wù)系統(tǒng)一期工程的開(kāi)發(fā)費(fèi)用合計(jì)三個(gè)億,包含硬件,這套系統(tǒng)需要結(jié)合鐵道部信息數(shù)據(jù)庫(kù)、還需要結(jié)合電話售票、窗口售票等相關(guān)數(shù)據(jù)的結(jié)合。12306不是一個(gè)簡(jiǎn)單的在線交易系統(tǒng),而是一個(gè)全國(guó)乃至世界最大的大宗物資貨運(yùn)系統(tǒng)?!?br/>
過(guò)了片刻,隨行的一位技術(shù)專(zhuān)家也說(shuō)道:“12306的技術(shù)確實(shí)非常難解決,利用現(xiàn)有的分布式數(shù)據(jù)庫(kù)、緩存、負(fù)載均衡技術(shù)已經(jīng)不能滿足需求?!?br/>
說(shuō)到這里,這名技術(shù)專(zhuān)家看向了羅晟補(bǔ)充道:“要知道,12306在春運(yùn)的時(shí)候,日均有近300億次訪問(wèn)量。如此天量級(jí)別的火車(chē)票查詢(xún)是影響12306性能的重要原因之一,大概率占了90%以上的訪問(wèn)量。更及棘手的是:峰谷的查詢(xún)有天壤之別,幾乎沒(méi)有辦法在成本和并發(fā)能力之間做一個(gè)好的平衡?!?br/>
傾聽(tīng)著的羅晟默默的點(diǎn)點(diǎn)頭,逝者對(duì)方把話說(shuō)完之后,他便問(wèn)道:“你們和阿里的合作是怎么解決的?”
那名技術(shù)專(zhuān)家坦言:“現(xiàn)在的做法是從幾個(gè)關(guān)鍵入口流量控制,保障系統(tǒng)可用性,但是會(huì)影響用戶(hù)體驗(yàn),仍然出現(xiàn)網(wǎng)站宕機(jī)、打不開(kāi)的現(xiàn)象,已經(jīng)遭來(lái)一片罵聲。”
說(shuō)著那名技術(shù)專(zhuān)機(jī)也是苦笑的搖了搖頭。
劉副總也說(shuō)道:“阿里免費(fèi)給12306提供技術(shù)支持,但是技術(shù)還是不夠硬,我們現(xiàn)在就把希望放在星云上了?!?br/>
羅晟不由得一笑,也是耿直的說(shuō)道:“劉總,首先我可以肯定的給你一個(gè)回復(fù),星云系統(tǒng)完全沒(méi)問(wèn)題,同時(shí)我可以保證在一周之內(nèi)就能實(shí)現(xiàn)為12306量身打造一整套從軟件到硬件的完整解決方案,但這個(gè)解決方案不會(huì)像阿里一樣免費(fèi)支持。”
劉總啞然,也是一笑,道:“愿聞其詳。”
羅晟思量了片刻,迅速組織好語(yǔ)言便說(shuō)道:“如果星云支持12306系統(tǒng)以后,把12306網(wǎng)站查詢(xún)?cè)L問(wèn)放到星云上。一般而言,查詢(xún)是多數(shù)售票系統(tǒng)訪問(wèn)量最大的部分,剛剛也聽(tīng)你們的專(zhuān)家說(shuō)了,90%左右。在交易相關(guān)的過(guò)程中,都會(huì)多次提交查詢(xún)請(qǐng)求,更不要說(shuō)現(xiàn)在有大量刷票軟件的出現(xiàn)所帶來(lái)的額外增加的工作負(fù)載了,這一切都讓余票查詢(xún)系統(tǒng)成為整個(gè)系統(tǒng)的壓力集中地?!?br/>
“我的解決方案是,星云介入后,把余票查詢(xún)模塊和12306現(xiàn)有系統(tǒng)做分離,具備獨(dú)立部署的能力;在云端上獨(dú)立部署一套余票查詢(xún)系統(tǒng),這樣12306和云上都有了一套余票查詢(xún)系統(tǒng),調(diào)度會(huì)更為靈活,目前星云集群服務(wù)器規(guī)模已經(jīng)達(dá)到了50000臺(tái)以上?!?br/>
在場(chǎng)的幾位鐵路集團(tuán)的技術(shù)專(zhuān)家一聽(tīng)也是暗暗咂嘴,難怪阿里的“飛天”系統(tǒng)這么不禁打,前者勉勉強(qiáng)強(qiáng)破千,而后者已經(jīng)達(dá)到了5萬(wàn)規(guī)模之巨,難怪羅晟會(huì)這么有信心。
接下來(lái),羅晟主要與鐵路集團(tuán)的幾名技術(shù)專(zhuān)家討論。
“今天上午我在得知消息順帶簡(jiǎn)單研究了一下‘12306’的服務(wù)端架構(gòu)?!绷_晟面向眾人有條不紊的說(shuō)道:“廣大訪問(wèn)者都在噴,但是我知道12306服務(wù)一上線試運(yùn)行,就承受著這個(gè)世界上任何秒殺系統(tǒng)都無(wú)法超越的QPS,上百萬(wàn)的并發(fā)再正常不過(guò)了。”
在場(chǎng)的幾名鐵路集團(tuán)的技術(shù)骨干人員內(nèi)心稀里嘩啦的感動(dòng),理解萬(wàn)歲啊。
不懂技術(shù)的領(lǐng)導(dǎo)最難溝通,覺(jué)得沒(méi)有盡力。
羅晟的話還是很有分量的。
過(guò)了片刻,羅晟補(bǔ)充道:“高并發(fā)的系統(tǒng)架構(gòu)要采用分布式集群部署,服務(wù)上層有著層層負(fù)載均衡,并提供各種容災(zāi)手段,所謂的容災(zāi)手段就是雙火機(jī)房、節(jié)點(diǎn)容錯(cuò)、服務(wù)器災(zāi)備等。保證系統(tǒng)的高可用,流量也會(huì)根據(jù)不同的負(fù)載能力和配置策略均衡到不同的服務(wù)器上?!?br/>
“即便如此,集群中的單機(jī)所能承受的QPS也是非常高的,那么如何將單機(jī)性能優(yōu)化到極致呢?要解決這個(gè)問(wèn)題要先弄明白一件事:通常訂票系統(tǒng)要處理生成訂單、減扣庫(kù)存、用戶(hù)支付這三個(gè)基本的階段,系統(tǒng)要做的事情就是保證火車(chē)票訂到不超賣(mài)、不少賣(mài)、每張售賣(mài)的車(chē)票都必須支付才有效,還要保證系統(tǒng)承受極高的并發(fā)。”
幾名鐵路集團(tuán)的技術(shù)專(zhuān)家連連點(diǎn)頭表示認(rèn)同,技術(shù)痛點(diǎn)就在這里。
羅晟繼續(xù)說(shuō)道:“下單減庫(kù)存。當(dāng)用戶(hù)并發(fā)請(qǐng)求到達(dá)服務(wù)端時(shí),首先創(chuàng)建訂單,然后扣除庫(kù)存,等待用戶(hù)支付。這種順序是我們一般人首先會(huì)想到的解決方案,這種情況下也能保證訂單不會(huì)超賣(mài),但也會(huì)產(chǎn)生一些問(wèn)題,第一就是在極限并發(fā)的情況下,任何一個(gè)內(nèi)存操作的細(xì)節(jié)都至關(guān)影響性能,尤其是像創(chuàng)建訂單這種邏輯,基本都需要存儲(chǔ)到磁盤(pán)數(shù)據(jù)庫(kù)的,對(duì)數(shù)據(jù)庫(kù)的壓力是可想而知的,12306應(yīng)該是用的甲骨文數(shù)據(jù)庫(kù),別花這個(gè)冤枉錢(qián)了,放到我的星云上?!?br/>
“第二是如果用戶(hù)存在惡意下單的情況,只下單不支付這樣庫(kù)存就會(huì)變少,會(huì)少賣(mài)很多訂單,雖然服務(wù)端可以限制IP和用戶(hù)的購(gòu)買(mǎi)訂單數(shù)量,但這也真心不算是一個(gè)好辦法?!?br/>
“然后就是支付減庫(kù)存了。如果等待用戶(hù)支付了訂單再減庫(kù)存,第一感覺(jué)就是不會(huì)少賣(mài)。但這是并發(fā)架構(gòu)的大忌,因?yàn)樵跇O限并發(fā)的情況下,用戶(hù)可能會(huì)創(chuàng)建很多訂單,當(dāng)庫(kù)存減為零的時(shí)候很多用戶(hù)會(huì)發(fā)現(xiàn)搶到的訂單支付不了,這也就是所謂的‘超賣(mài)’,也不能避免并發(fā)操作數(shù)據(jù)庫(kù)磁盤(pán)IO?!?br/>
“最后是預(yù)扣庫(kù)存。從上面兩種方案的考慮,可以得出結(jié)論:只要?jiǎng)?chuàng)建訂單,就要頻繁操作數(shù)據(jù)庫(kù)IO。那么有沒(méi)有一種不需要直接操作數(shù)據(jù)庫(kù)IO的解決方案呢?答案是有,就是預(yù)扣庫(kù)存,先扣除了庫(kù)存,保證不超賣(mài),然后異步生成用戶(hù)訂單,這樣響應(yīng)給用戶(hù)的速度會(huì)快很多。”
“那么怎么保證不少賣(mài)呢?用戶(hù)拿到了訂單,不支付怎么辦?訂單都應(yīng)該有效期,比如說(shuō)用戶(hù)五分鐘內(nèi)不支付,訂單就失效,就會(huì)加入新的庫(kù)存。訂單的生成是異步的,應(yīng)該放到即時(shí)消費(fèi)隊(duì)列中處理……”
劉副總聽(tīng)的云里霧里的,但是他發(fā)現(xiàn)羅晟和他帶來(lái)的幾個(gè)技術(shù)專(zhuān)家交流的愈發(fā)火熱,似乎也得出了一個(gè)信息。
找對(duì)人了!
這時(shí),羅晟打開(kāi)了房間里的墻面上的大屏幕,他也拿來(lái)了一臺(tái)筆記本工作電腦打開(kāi),示意眾人看向主投屏,自己一邊操作電腦一邊說(shuō)道:
“Go語(yǔ)言原生為并發(fā)設(shè)計(jì),我就采用Go語(yǔ)言給各位演示一下單機(jī)搶票的具體流程以及我優(yōu)化后的解決方案?!?br/>
“Go包中的init函數(shù)先于main函數(shù)執(zhí)行,也在這個(gè)階段主要做一些準(zhǔn)備性質(zhì)的工作。系統(tǒng)需要做的準(zhǔn)備工作有:初始化本地庫(kù)存、初始化遠(yuǎn)程redis存儲(chǔ)統(tǒng)一庫(kù)存的hash鍵值、初始化redis鏈接池。”
“另外還需要初始化一個(gè)大小為1的int類(lèi)型chan,目的是實(shí)現(xiàn)分布式鎖的功能,也可以直接使用讀寫(xiě)鎖或者使用redis等其他方式避免資源競(jìng)爭(zhēng),但是使用Channel更加高效,這就是Go語(yǔ)言的哲學(xué),不需要通過(guò)共享內(nèi)存來(lái)通信,而是通過(guò)通信來(lái)共享內(nèi)存。Redis庫(kù)使用的是redigo,下面是代碼:
【
//localSpike包結(jié)構(gòu)體定義
packagelocalSpike
typeLocalSpikestruct{
LocalInStockint64
LocalSalesVolumeint64
}
…
//remoteSpike對(duì)hash結(jié)構(gòu)的定義和redis連接池
packageremoteSpike
//遠(yuǎn)程訂單存儲(chǔ)健值
typeRemoteSpikeKeysstruct{
……
】
……
不知不覺(jué),時(shí)間已經(jīng)過(guò)去了一個(gè)半小時(shí),反正劉副總是聽(tīng)不懂,那些代碼看的暈頭轉(zhuǎn)向。
技術(shù)問(wèn)題終于討論的差不多了。
鐵路集團(tuán)的技術(shù)專(zhuān)家看向了劉副總并且?guī)е隙ǖ哪抗廨p點(diǎn)了一下頭,劉副總立馬就明白了,果斷的轉(zhuǎn)投看向羅晟問(wèn)道:“羅總,如果提供這么一整套完善解決方案,報(bào)價(jià)是多少?”
羅晟直言:“每年支付10個(gè)億?!?br/>
劉副總聽(tīng)到這個(gè)數(shù)字差點(diǎn)沒(méi)有一口老血噴出來(lái),12306票務(wù)系統(tǒng)一期工程的預(yù)算也才3個(gè)億,這樣的報(bào)價(jià)簡(jiǎn)直貴到難以接受。
……
()
中文網(wǎng)