12306與中國(guó)著名的互聯(lián)網(wǎng)企業(yè)進(jìn)行合作解決—整體架構(gòu)
針對(duì)類似于12306的高性能高并發(fā)系統(tǒng)設(shè)計(jì),童文童認(rèn)為12306網(wǎng)站完全可以和新浪、淘寶等大型互聯(lián)網(wǎng)公司進(jìn)行合作,通過他們的平臺(tái)進(jìn)行登錄,利用這些大型互聯(lián)網(wǎng)公司的資源與12306的平臺(tái)相對(duì)接,以分散海量并發(fā)所帶來的壓力,具體架構(gòu)設(shè)計(jì)可參考上圖。
在集成架構(gòu)方面,可采用以消息隊(duì)列為核心的異步機(jī)制把新浪微博、淘寶、騰訊這些公司平臺(tái)提供的互聯(lián)網(wǎng)售票應(yīng)用與12306互聯(lián)網(wǎng)售票數(shù)據(jù)服務(wù)系統(tǒng)集成起來。這種消息隊(duì)列為核心的異步機(jī)制進(jìn)行解耦的架構(gòu)有幾個(gè)最大的好處:
當(dāng)大量的并發(fā)的用戶(例如千萬級(jí)別的)在幾分鐘之內(nèi)甚至1分鐘之內(nèi)壓到新浪微博、淘寶、騰訊這些公司平臺(tái)提供的互聯(lián)網(wǎng)售票WEB應(yīng)用,所產(chǎn)生的壓力 由相應(yīng)的網(wǎng)絡(luò)、均衡負(fù)載器、互聯(lián)網(wǎng)售票WEB應(yīng)用的服務(wù)器給分別的承受掉。并且轉(zhuǎn)換成相應(yīng)的消息異步的傳到12306互聯(lián)網(wǎng)售票數(shù)據(jù)服務(wù)系統(tǒng)進(jìn)行處理,這 樣轉(zhuǎn)換給12306互聯(lián)網(wǎng)售票數(shù)據(jù)服務(wù)系統(tǒng)的并發(fā)壓力將會(huì)下降幾個(gè)數(shù)量級(jí)。
12306互聯(lián)網(wǎng)售票數(shù)據(jù)服務(wù)系統(tǒng)可以根據(jù)相應(yīng)的需求按需配置所需要的資源(例如機(jī)器數(shù)目和線程數(shù)目進(jìn)行處理)對(duì)不同的隊(duì)列進(jìn)行處理。并且由于采用 了消息隊(duì)列為核心的異步機(jī)制,在高峰期的時(shí)候肯定是大量的消息涌入以期待處理,在沒有采用消息隊(duì)列為核心的異步機(jī)制的時(shí)候我們需要的一次一條條進(jìn)行處理, 而這種情況下例如我們可以對(duì)登錄實(shí)現(xiàn)一次處理10條消息的批量處理,從而大大地降低對(duì)數(shù)據(jù)庫的壓力。
12306可以將前端交給這些公司合作一起解決高并發(fā)問題,當(dāng)然也可以自己獨(dú)立解決前端的并發(fā)問題,以避免合作過程中可能出現(xiàn)的問題。這對(duì)于整體系 統(tǒng)架構(gòu)設(shè)計(jì)而言,并不會(huì)有太大的變化,只是需要投入大量的成本而已。
焦點(diǎn)四:軟件層需要做哪些工作?
軟件層將直接決定整個(gè)系統(tǒng)應(yīng)對(duì)高并發(fā)的能力,其將應(yīng)用服務(wù)器與數(shù)據(jù)庫、存儲(chǔ)結(jié)合成為一個(gè)有機(jī)的整體,使數(shù)據(jù)在這些IT設(shè)備之間傳輸,可以說軟件層做得好與不好可能性能差異能達(dá)幾倍到一個(gè)量級(jí)。那么在以高并發(fā)為前提的情況下,軟件層要做什么呢?
百度首席架構(gòu)師林仕鼎認(rèn)為在解決請(qǐng)求尖峰時(shí)可采用threadpool或event-driven兩種做法。這兩種做法都需要自己維護(hù)請(qǐng)求隊(duì)列,也帶來了提高穩(wěn)定性的可能性。簡(jiǎn)單地說,就是增加flow control機(jī)制,上游根據(jù)下游的負(fù)載做throttling,反饋可以有ack/poll等多種做法,有時(shí)需要由最下游一路反饋到最前端。并采用延遲截?cái)?,?duì)于太老的請(qǐng)求,直接給出拒絕響應(yīng),讓它在應(yīng)用層重試。
4399架構(gòu)師曹政則提供了更多更具體的方式,他認(rèn)為可將存儲(chǔ)key- value化,因?yàn)榛旧喜樵兌际侵本€式的,所以key-value就是很好的工具;因?yàn)槌銎笨赡苄枰乙幌萝嚧?,座位,只能一一?duì)應(yīng)的查詢就不好用;弄 個(gè)redis帶個(gè)列表結(jié)構(gòu)進(jìn)去就可以了。春節(jié)放票總共多少?gòu)?又不是一次放出來,每張票對(duì)應(yīng)一個(gè)key,一個(gè)value,能吃多少內(nèi)存?后面跟個(gè)數(shù)據(jù)庫做 同步,這點(diǎn)數(shù)據(jù)量對(duì)于現(xiàn)在的服務(wù)器來說根本不是問題。并且在注冊(cè)登陸也可以在 mysql基礎(chǔ)上弄個(gè)redis掛在前頭響應(yīng)以提高查詢速度。
實(shí)際上,在12306在線購(gòu)票系統(tǒng)中,查詢操作是很常見,因?yàn)槟阈枰樵冘嚧?,還需要查詢余票?;谶@點(diǎn),曹政認(rèn)為可將查詢結(jié)果緩存化、靜態(tài)化,這可通過兩個(gè)步驟實(shí)現(xiàn),起始地,目標(biāo)地查詢 – 常見查詢目標(biāo)(如北京到成都)全部預(yù)制緩存。非常見查詢目標(biāo),基于第一次查詢的結(jié)果緩存,這樣查詢車次基本上無壓力。
查詢有票狀態(tài)就更簡(jiǎn)單了,因?yàn)槠睌?shù)只有有票,無票兩個(gè)狀態(tài),某日某車次作為一個(gè)key-value類型存儲(chǔ)(仍用redis即可)。某類車票發(fā)生從 有到無或從無到有的變化,才通知緩存更新。更新是后臺(tái)通知的,而非基于用戶查詢。比如某車次硬臥票售完,通知一次更新,硬座售完,通知一次更新,軟座售 完,通知一次更新。以此類推,這樣的緩存更新次數(shù)極少。而且可以給前端返回甚至靜態(tài)結(jié)果(基于查詢條件生成靜態(tài)結(jié)果,是個(gè)Seoer都會(huì)的,后臺(tái)在票數(shù)變 化時(shí)通知更新,這樣結(jié)構(gòu)上就與前端查詢無關(guān)了,而且一樣可以保持實(shí)時(shí)性)。
最后還可對(duì)前端緩存進(jìn)行處理來提高響應(yīng)速度。可能大多數(shù)人都被10億PV給嚇到了,但實(shí)際上這里面有很大的水分,因?yàn)橛泻芏嗫赡苁抢么a或者腳本 進(jìn)行的自動(dòng)刷新,自然而然就會(huì)產(chǎn)生較大的泡沫,而實(shí)際上絕對(duì)不會(huì)有那么多。基于這點(diǎn),則可通過緩存來避免“爆機(jī)”,并且有例子證明,這樣做的效果是能夠應(yīng) 對(duì)一小時(shí)20億的刷新,12306的10億刷新根本就不成問題。
當(dāng)然,網(wǎng)上的各種關(guān)于軟件層的建議還有很多很多,包括之前提到的云風(fēng)的排隊(duì)系統(tǒng)也應(yīng)該屬于軟件層的內(nèi)容,因?yàn)槠脑?,在此我們僅選取了幾個(gè)較為典型的建議。
焦點(diǎn)五:系統(tǒng)該如何優(yōu)化?
系統(tǒng)優(yōu)化是必不可少的環(huán)節(jié),每一個(gè)成熟的網(wǎng)站和系統(tǒng)都是通過不斷優(yōu)化而來的。而12306網(wǎng)站最早暴露出來的也是優(yōu)化問題,隨后經(jīng)過網(wǎng)友深挖,從12306網(wǎng)站前端的網(wǎng)頁設(shè)計(jì)到后端的數(shù)據(jù)、緩存、負(fù)載均衡、數(shù)據(jù)分區(qū)等一系列問題都提出不同的優(yōu)化方案。
12306網(wǎng)站前端性能優(yōu)化技術(shù)分析
從時(shí)間上來看,首先引發(fā)12306網(wǎng)站擁堵的是網(wǎng)頁的問題,從12306的首頁來看,其總文件大小在900K左右,在極端情況下,如果所有人都是第 一次訪問的話,那么每個(gè)人都需要下載1M大小的文件,如果需要在兩分鐘內(nèi)返回的話,那么所需的帶寬需要66Gbps,當(dāng)然這是極端的情況。那么在這種情況 下就需要對(duì)網(wǎng)頁大小進(jìn)行調(diào)整,盡量少用圖片,因?yàn)閳D片非常消耗帶寬,在這種高并發(fā)的情況下,即使1K大小的文件也極有可能引發(fā)“蝴蝶效應(yīng)”。
同時(shí),由于對(duì)12306網(wǎng)站的訪問是部分地域的,可能不同的Web服務(wù)器承受這不同的壓力,這種情況下可通過DNS負(fù)載均衡器將用戶訪問平均分配到各個(gè) Web服務(wù)器上,因?yàn)镠ttp的請(qǐng)求都是短時(shí)的,所以很簡(jiǎn)單的負(fù)載均衡器就能完成這一動(dòng)作。并且,CDN在這個(gè)環(huán)節(jié)能夠提供很大的幫助。
并且,IBM 軟件架構(gòu)師景文童認(rèn)為,12306網(wǎng)站在后期應(yīng)該增加對(duì)智能移動(dòng)終端的支持,那么從當(dāng)前的整體帶寬來看,盡量不用或少用圖片,并對(duì)網(wǎng)頁進(jìn)行優(yōu)化將有助于提 高網(wǎng)站的訪問速度。在都不是非首次訪問的前提下,瀏覽器會(huì)緩存相當(dāng)一部分內(nèi)容,這就會(huì)明顯減少帶寬占用,于是負(fù)載一下子從前端遷移到了后端,數(shù)據(jù)處理瓶頸 一下就凸顯出來,訪問者不斷刷出的500錯(cuò)誤即是明證。
除了上述所說的這些之外,還可通過減少前端網(wǎng)頁的鏈接數(shù)、頁面靜態(tài)化以及之前提到的緩存技術(shù)來對(duì)網(wǎng)站前端進(jìn)行優(yōu)化。這些方法能夠明顯解決用戶無法登 陸或者訪問緩慢等問題,但并不能解決問題真正的實(shí)質(zhì)——購(gòu)票。因?yàn)樯婕暗綄?duì)數(shù)據(jù)庫進(jìn)行查詢以及寫入等操作,后端優(yōu)化就顯得尤為重要。
12306網(wǎng)站后端性能優(yōu)化技術(shù)分析
關(guān)于后端性能優(yōu)化技術(shù),陳皓在其博客中表示,可通過數(shù)據(jù)冗余、數(shù)據(jù)鏡像、數(shù)據(jù)分區(qū)以及后端的動(dòng)態(tài)負(fù)載均衡來達(dá)到提高訪問速度的目的。
數(shù)據(jù)冗余就是將數(shù)據(jù)庫的數(shù)據(jù)冗余處理,也就是減少表連接這樣的開銷比較大的操作,但這樣會(huì)犧牲數(shù)據(jù)的一致性。但這樣做的風(fēng)險(xiǎn)較大,并且現(xiàn)在常用的方法就是利用NoSQL來做數(shù)據(jù),數(shù)據(jù)冗余了,訪問加快了,但是數(shù)據(jù)一致性就會(huì)存在較大的問題。
利用后端優(yōu)化來提高訪問速度的第二個(gè)方法則是數(shù)據(jù)鏡像,現(xiàn)在幾乎所有的主流數(shù)據(jù)庫都支持鏡像。鏡像的好處就是可以做負(fù)載均衡。把一臺(tái)數(shù)據(jù)庫的負(fù)載均 分到多臺(tái)上,同時(shí)又保證了數(shù)據(jù)一致性(Oracle的SCN)。最重要的是,這樣還可以有高可用性,一臺(tái)廢了,還有另一臺(tái)在服務(wù)。但數(shù)據(jù)鏡像后的數(shù)據(jù)一致 性仍然是一個(gè)復(fù)雜的問題,因?yàn)橐獙?duì)單條數(shù)據(jù)進(jìn)行分區(qū),將其均分到不同的服務(wù)器上。
數(shù)據(jù)鏡像不能解決的一個(gè)問題就是數(shù)據(jù)表里的記錄太多,導(dǎo)致數(shù)據(jù)庫操作太慢。所以,把數(shù)據(jù)分區(qū)。數(shù)據(jù)分區(qū)有很多種做法,一般來說,數(shù)據(jù)分區(qū)包含以下幾 種主要的方式:把數(shù)據(jù)把某種邏輯來分類、把數(shù)據(jù)按字段分,也就是豎著分表、平均分表或者同一數(shù)據(jù)分表等。
數(shù)據(jù)分區(qū)可以在一定程度上減輕負(fù)載,但是無法減輕熱銷商品的負(fù)載,對(duì)于火車票來說,可以認(rèn)為是大城市的某些主干線上的車票。這就需要使用數(shù)據(jù)鏡像來 減輕負(fù)載。使用數(shù)據(jù)鏡像,你必然要使用負(fù)載均衡,在后端,我們可能很難使用像路由器上的負(fù)載均衡器,因?yàn)槟鞘蔷饬髁康模驗(yàn)榱髁坎⒉淮矸?wù)器的繁忙程 度。因此,我們需要一個(gè)任務(wù)分配系統(tǒng),其還能監(jiān)控各個(gè)服務(wù)器的負(fù)載情況。當(dāng)然服務(wù)器負(fù)載均衡的技術(shù)有很多,每種方法都有各自的優(yōu)缺點(diǎn),這個(gè)可能要根據(jù)實(shí)際 情況進(jìn)行選擇。
12306高性能高并發(fā)系統(tǒng)特點(diǎn)總結(jié)
實(shí)際上,通過上述的這么熱議焦點(diǎn),我們可以發(fā)現(xiàn),要建設(shè)一個(gè)類似于12306在線購(gòu)票系統(tǒng)還是面臨著諸多難題,從系統(tǒng)層面上講,其必須必備高性能、 高可擴(kuò)展性以及高可靠性等特點(diǎn)。同時(shí),整個(gè)系統(tǒng)從架構(gòu)設(shè)計(jì)到網(wǎng)頁設(shè)計(jì),甚至每段代碼的編寫都必須經(jīng)得起嚴(yán)格的考驗(yàn),網(wǎng)頁代碼力求簡(jiǎn)單、實(shí)用,因?yàn)槟桥乱恍?段代碼問題在面對(duì)瞬時(shí)海量高并發(fā)時(shí)都有可能引發(fā)“蝴蝶效應(yīng)”。
在春運(yùn)期間,對(duì)于廣大的貧苦老百姓而言,火車票的超高性價(jià)比和相應(yīng)的方便性,使得每張票都成為稀缺資源和緊俏商品。而在12306系統(tǒng)開始售票那一 瞬間,必然有成千上百萬的人一擁而上。盡管從鐵道部發(fā)布的數(shù)據(jù)來看,其最高的一天一共賣出了188萬多張票,這個(gè)數(shù)據(jù)放在一天來看的話,確實(shí)不多。但是如 果是在短短幾分鐘之內(nèi)呢?那整個(gè)系統(tǒng)承受的壓力自然不言而喻。
盡管此次鐵道部采用的是分地區(qū)分時(shí)段售票,但所售票數(shù)跟搶購(gòu)人數(shù)之間是沒有關(guān)系的。同時(shí)因?yàn)樵谧钤缒且粫r(shí)段售票時(shí)就沒有解決并發(fā)所帶來的壓力,使得 已經(jīng)開始發(fā)售第二時(shí)段的票時(shí),仍有大量的人在不停地刷新,使得訪問人數(shù)再次增加,系統(tǒng)壓力亦隨著增長(zhǎng)。那么整個(gè)系統(tǒng)就必須使得在第一時(shí)段內(nèi)賣出所有的票, 而這個(gè)時(shí)間點(diǎn)可能就只有短短的幾分鐘(開始售票那幾分鐘,因?yàn)榛疖嚻笔沁h(yuǎn)遠(yuǎn)小于想要買票的人數(shù)的)。
除了整個(gè)系統(tǒng)需要滿足高性能需求之外,還得同時(shí)具備高可擴(kuò)展性(高可伸縮性)。因?yàn)閺臍v年來的經(jīng)驗(yàn)來看,鐵道部的并發(fā)高峰通常是在節(jié)假日發(fā)生,如五 一、十一長(zhǎng)假等,春運(yùn)則是最大的一個(gè)并發(fā)高峰。而目前的情況看來,12306在線購(gòu)票系統(tǒng)雖然不能應(yīng)對(duì)春運(yùn)高峰,但在平時(shí)售票卻還是沒有問題。這就使得這 個(gè)系統(tǒng)必須具備高可伸縮性,在并發(fā)高峰來臨之前,能夠通過簡(jiǎn)單的加機(jī)器或者與新浪、淘寶、騰訊等大型互聯(lián)網(wǎng)公司合作來共同應(yīng)對(duì)這些并發(fā)高峰。
在具備上述兩個(gè)特點(diǎn)的同時(shí),還得具備高可靠性。這么大的并發(fā)單靠一臺(tái)機(jī)器是不可能實(shí)現(xiàn),必須采用集群來分散壓力。而在集群中,必須防備機(jī)器故障,單臺(tái)機(jī)器故障之后不能影響其他機(jī)器的正常運(yùn)轉(zhuǎn),并且還必須在短時(shí)而將故障修復(fù)。
除了上述三大必備性能之外,如果想擁有更好的用戶體驗(yàn),那么還得具備一些其他的特點(diǎn)。目前移動(dòng)互聯(lián)網(wǎng)正飛速向前發(fā)展,各種智能移動(dòng)終端(如智能手機(jī)、平板電腦)層出不窮,作為一個(gè)方便可行的系統(tǒng),那么還應(yīng)該對(duì)這些移動(dòng)終端提供支持。
另外,從現(xiàn)今角度除外,鐵道部所售出的總票數(shù)是遠(yuǎn)遠(yuǎn)小于想要買票的人數(shù)的,供小于求,必然導(dǎo)致投機(jī)分子的存在,如“黃牛”,那么這個(gè)系統(tǒng)就還得作出 一些措施來防范利用腳本、程序進(jìn)行刷票的行為。刷票也是增加并發(fā)的一個(gè)因素之一,防止刷票也從另一個(gè)方面減少了并發(fā),提高整個(gè)系統(tǒng)的可用性。