大麦网技术二三事

杭州周杰伦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 有的放矢,摸清硬伤

谈系统优化,不能泛泛而谈,一张嘴不是一系列高大上的方案、就是现有的不堪到须要所有推翻从新全来一个理想中的完美架构。一般只有演化成功的系统,没有一开始就设计成功作得完美的系统。

鉴于篇幅有限,暂且就先分享到这里。

相关文章
相关标签/搜索