大麥網技術二三事

杭州周杰倫2017年項目,大麥網搶票系統搶癱了,據傳阿里內部炸了鍋,大麥在阿里序列裏直接進入了被鄙視鏈的第一名,江湖上也是聲名狼藉。做爲大麥故人(大麥網前技術總監及初創團隊核心),我已是不止一次的在各類場合聽到諸如「大麥網技術水平太爛了」、「大麥基本沒什麼技術含量」、「大麥的技術還處於舊石器時代」等評論。對於差評,系統宕機擺在眼前,也確實是無需辯駁;但做爲大麥網初創團隊成員與最有資格談論大麥技術的成員之一,猶豫再三,仍是決定聊一聊大麥網的一些技術往事,只爲緬懷。程序員

我是2008年4月份加入的大麥,這是我第一份工做(若是不算大學時兼職的話,初中開玩Q-BASIC,上四年大學幹了兩年兼職,寫了三四十萬行代碼,挑戰杯大賽獲獎者)。面試

那時候尚未「大麥網」,只有「中國票務在線」。在某個陽光明媚的週末上午,我走進了東中街32號樓旁邊的元嘉國際公寓821面試,這是一套loft的公寓。進門前我曾一度懷疑本身是否是進了傳銷窩點,怎麼看也不像一家正規公司。我和個人面試官、往後的好哥們-王威聊得很投機,咱們都喜歡技術,屬於把技術當生活的那類人,並不以爲這是一份工做,而是既讓本身玩、居然還給錢的美事(玩中文分詞、搜索引擎、元搜索…),出門時我已經決定要來這家公司了。redis

2009年初咱們在快速作死了旅遊、機票、SNS、酒店、客棧、電影……等一系列產品後,最終決定把演出購票作深,打造一個電商模式的購票網站。對於決定去作這件事情也有點逗,我、王威作死了上述一系列產品以後,心情很沮喪,滿滿的挫敗感,咱們一塊兒在東方銀座停車場的花壇邊上坐了一夜,不說話、抽着煙、看着來來每每的人,摳着腳(不是我)。記不清後來怎麼起的話題,總之最後把煙一丟,決定作個演出購票電商網站,而後次日上班就開始開發,接下來就是滿滿的五年加班歲月,平均天天工做超過12小時,幾乎沒有週末和節假日,每天見識凌晨四點鐘的北京街頭。神馬睡袋賬篷的Low爆了,咱們是椅子上、會議桌上、檯球桌下、辦公司的角落地上……都睡遍了。算法

大麥網站部分的整個技術體系我一手搭建(截止至2015年大麥重構前),同時我也是大麥用戶庫裏的第2號用戶(哈哈哈),2010年定崗技術總監,至2013年12月我離開前,大麥網歷年歷屆的搶票準備及協同工做都是由我主持。2013之因此離開,是由於大數據剛剛興起,我但願可以在大麥內啓動大數據相關的事情,可是那會你們都看不懂,因此一直沒獲得支持,因而便放棄了大麥的期權離開,成爲一家公司的技術合夥人,作了一些數據相關的業務(因此也淪爲了大麥初創團隊裏惟一一個沒有期權收益的成員)。數據庫

元嘉國際公寓821,大麥網的起點
元嘉國際公寓821,大麥網的起點

談起大麥,大麥是一家悶頭作事、行事低調的公司,大麥的技術團隊也很是低調。我在大麥的6年時光裏,咱們歷來沒有在任何公衆場合發過言說過事。實際上,在大麥網前期,因爲硬件的投入不多,因此對技術的要求到了近乎苛刻的地步。2013年我離開前,對團隊硬性要求是頁面服務端執行耗時100毫秒算及格線(含選座、下單),每一個頁面上線前先壓力測試看達標不達標,不達標所有打回繼續優化。咱們對代碼的優化是先把代碼註釋成空頁面,而後一行一行加代碼,看執行耗時增長了多少去優化的。我曾逼着某同窗連續加班了三個通宵,把業務頁面從1秒多,優化到了300毫秒、繼續優化到了100毫秒、60毫秒……(幸虧不恨我~)。咱們用4臺服務器扛過幾萬人的瘋狂搶票沒有掛(2009李宇春演唱會),雖然系統反應慢了點,提及來都是淚……慢的緣由之一是由於買的水晶頭質量太差,其中一臺服務器內網線的水晶頭鬆了,流量所有走了外網……(雖然咱們窮~但那會咱們人窮志不短,妄圖拿三五臺服務器開始作一個改變幾千萬人購票體驗的事情)後端

大麥技術團隊前期奉行的是工匠精神,有許多令咱們驕傲的東西。或許是後續的傳承出現了誤差。言歸正傳正傳聊技術,本文不聊負載均衡、分表分庫、SOA、緩存、CDN、雲……等一系列滿街跑的程序員無論實操沒實操過,一張口都能侃幾句的「大併發高負載解決方案」。時間、篇幅、精力都有限,也沒法長篇大論,所以我會從幾處細節切面入手,簡單聊一聊。緩存

01 在線選座核心技術

在線選座,如今已經應用得很是廣泛了,從演出到電影、到機票,被應用得爐火純青。若是我沒有記錯的話,大麥應該是國內最先在線上對C用戶提供在線選座的公司,第一個版本咱們參考了TicketMaster ,09年李宇春第一次正式使用 。 當時是遙遙領先於國內任何一家公司的同類產品,後續競友們也出了一系列同類產品,且投入的服務設備甚至比大麥還多 ,卻無一例外沒扛過搶票高併發。緣由在於大麥的在線選座在一些技術細節上處理得很是好,甚至現有的大麥技術團隊都並不清楚本身的系統是怎麼作的,實際上大麥的技術方案尚未實施到極致,還有提高的空間。離開後我進一步思考了下能夠採用如下方案:服務器

一、基於bit設計的座位數據傳輸協議

注意,是Bit,不是Byte、不是JSON、不是XML。截至今日,我看了許多在線選座的產品,包括行業內所謂神級公司的,無一例外都在用JSON,最多作了個GZIP壓縮。固然了,財大氣粗能夠拿服務器和網絡帶寬去扛,也是無可厚非的。壓縮算法是通用算法,耗費服務器計算資源,在數據協議自己沒有優化到極致狀況下我是禁止使用的。大麥在線選座的第一個版本用的是JSON數據作座位圖數據傳輸,一個場次座位數據量將近1MB,在打開選座的時候能看到進度條加載的明顯痕跡,然後來新數據協議實施完成後根本看不到進度條加載,由於同等信息數據傳輸量已縮小到了1KB左右。不只僅是數據量縮小了1000倍的事情,基礎好的同窗應該能看明白這意味着什麼,1KB的報文比1MB的報文在IP數據分片傳輸上的性能和可靠性要高出多少。網絡

這裏會牽涉到大量的位運算和數據類型基礎知識,因此搞不懂long型數據64bit相比int型數據32bit意味着什麼的小夥伴請繞行。架構

1)文本協議換成非文本協議

JSON等文本協議的優勢在於簡單直觀,肉眼可見,好開發、好維護。可是有些關鍵場合追求極致仍是很是有必要的。以一個數字「1234567890」爲例,在JSON協議中它須要佔用的字節數是:10byte=80bit,而用int型只有4byte=32bit,對於一個座位ID動不動10位數字以上的系統,光傳輸1000個座位ID有效數據量差異就是:(80-32)*1000=48000bit=6000byte 約等於6KB,再加上JSON格式裏的「{」、「}」、「=」、"""、動輒五六個英文字符的「seatid」屬性名……可想而知多了多少數據量。

2)絕對值用相對值代替

講這條以前,咱們先看則科幻小故事,我即是受了這個故事的啓發:

「一個外星人偶然來到了地球,以爲地球頗有意思,想帶資料回去。可是由於是偶然來的,本身的飛船不夠大,不可能放下不少樣本。因而外星人找到了一套大英百科全書,以爲這個很好,準備帶回去。可是發現那還不行,由於那一套太多了,仍是過重了。外星人就把字母所有用數字代替,因而外星人獲得了一串長長的數字,經過飛船的計算機所有按照百科全書順序排列好後準備帶走,可是外星人又發現飛船上的計算機還要存儲不少畫面和視頻,那串大英百科全書數字太長了,佔了不少硬盤空間——咱們假設外星技術也須要硬盤。那怎麼辦呢?外星人就測量了本身飛船精確的長度後,把飛船假設爲1。又把那串長長的‘大英百科數字’按照小數點後的模式,參照飛船長度,在飛船外殼上某處刻了很小的一個點。因而外星人回去了,他只刻了一個點,卻帶走了大英百科全書。回去只要測量出飛船的長度,再找到那個點在飛船上的位置……」

同一場演出的座位ID,通常是同一個數量級,好比第一個座位ID是「2010092012」,最後一個座位ID極可能是「2010093012」,在數據流裏一大串「20100920十二、201009201三、2010092014…2010093012」,我都感受本身傻。那麼,爲什麼不記錄下起始座位ID,後續全部座位ID都只記錄與它的誤差值呢?因而就變成了「20100920十二、一、二、3…1000」的形式,是否是連文本形式都看起來乾淨利落的減小了許多?不止於此,繼續閱讀下一條。

3)無視既定的數值類型,按需配位

用到位運算的時候到了。上面聊到long型和int型,long型數值64bit支持從-9223372036854775808~9223372036854775807範圍的數字,int型數值32bit支持-2147483648~2147483647範圍的數值,都別說上面第2)條提到的相對值數字了,就是用絕對值數字你家賣票賣到下輩子座位序號也超不出這個範圍啊,更況且還用不着負數 T_T。一個區域1000個座位加載下來,誤差值最大超不過1024,只須要10bit的空間就足以存儲單個座位ID了,既有數據類型ubyte佔8bit最大值255不夠用,ushort佔16bit最大值65535太浪費,咱們須要一個只佔10bit的數值……OK,把int、long、byte、字節通通從腦子裏抹掉吧,眼前是一串「0101010101……」到無限長的數據流,老老實實用">>"、"<<"左右移動着玩吧。

4)座位狀態2bit

座位有多種狀態,好比「可售」、「已售」、「鎖定」等,直接跟在座位ID後面拿2bit搞定吧。。。00、0一、十、11,還能再支持一個狀態~

5)一個座位4個座標值減小到1個

這個估計是最傻逼的設計了,由於選座的每一個座位是須要在場館背景裏畫出來的,所以須要有每一個座位的座標。問題是選擇了四個點來肯定一個座位……T_T,尼瑪的座位都同樣長寬,記錄最左上角的一個座標不就完事了麼……

二、說能賣的座位不必定能賣,說不能賣的座位必定不能賣

熱門演出搶票每每搶得血流成河,常常小一萬張票放出去30秒就搶沒了,沒搶到的粉絲們網上罵聲一片。不過話說系統都是我寫的我這麼多年居然沒能成功搶到一次票[痛哭]。流量高到平時120倍,先別提分表分庫拿數據庫集羣頂的方案的,大麥那會尚未阿里爸爸,沒有動不動撥幾個億先花着的待遇。有次我協調7臺服務器協調得鼻青臉腫,有一臺仍是調撥了部署着郵件服務端的破機器。怎麼辦啊,總不能兩手一攤說搞不定了吧。。。窮家窮當,繼續想轍啊。

座位數據在搶票那會是高實性數據,別期望在緩存裏完成全部工做,出張重票你就哭去吧。琢磨來琢磨去想到一招能夠解決:把全部座位狀態預先同步到redis裏(記住,一個座位一個坑),接下來對過來鎖座的請求先訪問緩存,緩存說能賣,很差意思不能相信你,穿透到後端數據庫詢問狀態加鎖座;緩存說不能賣,那鐵定不能賣,很差意思您再搶其它座位去吧。。。

此舉可讓數據庫壓力瞬間降低好幾個數量級。

選座技術先聊到此,其它的部分都沒什麼難點,自行腦補。
本文第四部分附有我作的併發數據分析,感興趣的同窗能夠算算數,看看是多少帶寬、多少服務器、支撐了多少併發。

02 熱門項目搶票的技術準備工做

當初咱們在每次大項目前都會作很是精細的數據分析,對購票過程當中系統的流程進行詳細切分,評估業務過程當中每一個環節的併發壓力 ,進行系統調優。以數據來評估和驅動系統準備工做,絕對不是粗放式地抱着上百臺的服務器,算算服務器數差很少就洗洗睡去了。

一、搶票活動CheckList

從2009年起經歷了不少大型項目的搶票,什麼樣的狀況都經歷過(譬如服務器鬆了個水晶頭、機房出口帶寬被流量懟死了服務器集體所有失聯、正搶着票呢辦公室忽然斷網等等許多人這輩子都碰不上的狀況),總結了不少的經驗,造成CheckList。每當有新熱門項目時就拿出CheckList逐項檢查看各項工做是否作到位。每場搶票活動結束後仔細總結,再往CheckList上補上幾條。

CheckList裏的每一條背後,都有一場血的教訓。舉幾個栗子來講吧:

1)主要系統負責人配備3G上網卡:某次搶票活動進行中,辦公室寬帶掛了,大麥網直接失控裸奔……今後之後,搶票開始前都給主要的系統負責人配3G上網卡;
2)CRM客服系統大查詢操做進行限制:某次搶票活動進行中,某分公司一客服MM手一抖,點擊了一下訂單彙總,數據庫直接宕了……今後之後,開搶前先把客服系統裏牽涉到大查詢的操做全關閉了;
3)短信通道餘額確認:某次搶票活動進行中,用戶都沒收到短信,由於短信通道錢用完了……
4)大麥網上第三方圖標及JS移除:某次搶票,一開票網頁加載不完,一查頁尾上掛着的某權威機構的JS直接被懟死了,資源等待中直至超時,致使大麥的頁面加載不完(赤裸裸的躺槍啊尼瑪聲淚俱下了)
5)搶票前機房設備巡檢:某次搶票,某臺服務器的水晶頭鬆了,數據流量所有走了外網系統超級慢……
6)搶票時機房派人值守:某次搶票,機房忽然失聯,從哪都鏈接不進服務器,大麥網直接失控裸奔……

滿滿的掛滿了淚……

二、系統流程及負載評估表

咱們會對系統流程詳細分解後,預測各系統切面須要達到的負載量,反覆優化與壓力測試:

三、應對項目時職責明確、分工清晰

準備每一場項目,都如行軍打仗。戰場上最怕的是亂,在出現突發事宜時,調度有序、各司其職很是重要,是快速響應和故障處理的基礎。咱們會明確好各部分的分工與責任人。

四、項目後總結分析

沒有總結就沒有收穫,失敗不可怕,怕的是盲目的失敗。所以每次項目結束後,須要對系統負載參數進行仔細總結與分析。舉個分析的栗子(水平好的同窗能夠算算數):

03 有的放矢,摸清硬傷

談系統優化,不能泛泛而談,一張嘴不是一系列高大上的方案、就是現有的不堪到須要所有推翻從新全來一個理想中的完美架構。一般只有演化成功的系統,沒有一開始就設計成功作得完美的系統。

鑑於篇幅有限,暫且就先分享到這裏。

相關文章
相關標籤/搜索