图片-精准获客

别再对12306吐槽不断啦,有能耐你自己来设计它的架构。

图片[1]-别再对12306吐槽不断啦,有能耐你自己来设计它的架构。-精准获客

我曾在淘宝编写过一段时间代码。2012年,我在一家百强民企担任电商副总,当时在艰苦的条件下,带队开发了一个B2C网站,采用支付宝和银联支付通道,年营业额达到千万级(虽然数额不算大,但该网站确实投入了实际运营)。

那时,我对12306嗤之以鼻,觉得它做得很差,认为自己能带领团队花几百万,用半年时间做出一个更好的订票系统。于是,我狂妄地想做一个开源订票系统给他们。我花了一星期思考建立数据模型,当思考到库存环节时,才发现12306的库存复杂性远超淘宝和京东,运算量也大得多。传统的分布式数据库、缓存和负载均衡技术,无法满足12306的需求。

平时,12306就像一个普通的电商网站。但到了黄金周,它就变成了一个全站商品都参与秒杀、所有SKU都是动态库存的“变态”网站。

即便不考虑线下的电话、代售点等渠道,要搭建一个12306这样的系统,当时估算最少也需要千万级别的硬件投入(这只是估算,未精确计算,可能与实际有较大差距。总之,我不敢保证说得一定对,12306的业务或许没我说的这么复杂,但绝不像某些人说得那么简单),软件和人力成本还需另算。那些叫嚷着只要40台服务器、2个架构师和4个程序员,大谈分库分表和前端CDN的人,不过是纸上谈兵。有些人做了三年CMS和BBS,就凭借这点经验批评12306,实在太天真。

媒体人批评12306,是因为他们不懂技术,没有能力和耐心去分析背后的难度。技术人员批评,则是因为大部分技术人员在短时间思考时,容易陷入过于乐观的误区。典型的例子就是估算工作量,程序员往往会估算出一个极短的工期,把写程序的工作简单地想象成打字员照着稿子敲键盘。

我认为知乎上那篇文章并非在为12306“洗地”。排名第一和第二的答案都很客观。淘宝的技术比12306强大很多,淘宝如今的系统是投入了10倍于12306的资金、时间和人才才搭建起来的。根本原因还是铁路运力无法满足春运需求,这问题淘宝也解决不了。

12306这一年进步显著。从前端的动画验证码、分时段抢票,到后端的去小型机、虚拟化、内存数据库的应用,可以说,12306是中国政府机关打造的最强大的网站(电商系统)。能在短短一两年内有如此大的改变,几乎是个奇迹,连一些市场化的民企,甚至上市公司都难以企及(比如51job和ctrip)。

没有亲身经历,就不知道其中的难处。在网上批评12306的人,大多形成了【国企 = 垄断 + 腐败 + 低效 】的思维定式,小部分人则是真的低估了它的难度。

至于12306一期工程3个亿(含硬件)是否昂贵,我不做评价,只提供一个参考数字。百度一年的研发费用(不含硬件)是10亿,这个数字可从百度财报中查到。3亿看似是个大数目,但在超大型的电商系统、搜索引擎系统中,其实不算天文数字。

下面解释一下,为什么秒杀压力大,以及为什么12306的动态库存很复杂。

秒杀

2013年12月25日前后,天猫举办了一个圣诞季积分兑换活动,持续了几天。25号上午10点12分,放出了15000个天猫魔盒(在淘宝集市大概卖190 – 230块),从成交记录看,19秒内就被抢完了。

实际上,我也参与了这次秒杀。当天的题目很简单(请输入xxx汉字的拼音首字母),我大概5秒内就答题完成并提交了订单,结果却被告知排队的人太多,挤不进去,还提示14秒后重试。人多是因为题目简单,门槛越低,5秒内涌入的人就越多。要是题目换成【2克浓度为3%的U235在大亚湾核电站能发多少KW的电】,5分钟内估计都不会有1万5千人跟我竞争。

我想着14秒后估计没机会了,就重新答题秒杀,结果出现了服务器错误页面。反复刷新几次,就提示秒杀结束了。

我在群里问同事,不到10个人回复我,都说没抢到(也许抢到的人闷声发大财,没回复我)。

淘宝的技术水平如何呢?两年前公开的数据显示,淘宝至少有4000名技术人员、4万台服务器。2013年11月11日,淘宝成交额达351亿,2012年全年成交额超过1万亿。

淘宝拥有众多自主研发团队,涉及服务器、交换机(网上能搜到淘宝公开的绿色服务器开放标准);操作系统(Linux Kernel taobao版,yunos手机操作系统暂不计入)、Web服务器(Tengine)、Java语言虚拟机(JVM taobao版)、数据库(MySQL内核taobao版,google和facebook也有自己的版本,HBase淘宝版、还有自主开发的OceanBase)、负载均衡器(LVS,LVS始创人在淘宝担任研究员)、Java运行容器(Jboss,其创始人之一王文彬在淘宝任副总裁)。

淘宝还有数不清的开源项目和中间件,如高性能Java通信中间件HSF、分布式数据库中间件TDDL、异步消息系统notify等。

以淘宝这样的技术水平,为何在秒杀时也不能让每个用户都感觉顺畅呢?

一是要遵循物理原理,一台服务器每秒能承受的计算量有极限,无论怎么优化,采用多高效的算法和编程语言,都无法突破某个极限。就像汽车发动机驱动的F1赛车,至今也无法突破400公里的时速(超音速推进号那种由飞机引擎驱动的时速不算)。若想深入了解,可从著名的C10K问题开始研究。

二是要考虑经济效益。十一黄金周时,北京主城区到八达岭长城的道路拥堵不堪,但不能因为黄金周的高峰,就把这段路修成10车道的长安街那样的高速公路。否则,花费将是天文数字(12306的3个亿大概只够修1 – 3公里)。路修好了,黄金周时能开到80公里/小时,但平时呢,难道给两边居民晒谷子用?

淘宝目前的硬件和带宽数量,已超出日常运营需求,就是为大促销预留了很大的余量(众所周知的双十一、双十二,其实基本每个季度都有大促销,每月有促销,甚至天天都有——聚划算)。amazon当年为应对黑色星期五的大促销购置了大量服务器,平时订单量减少后,就把富余的服务器用于云计算。顺便提一下,阿里云是中国第一、世界领先的云计算服务商,发展路径和amazon有点相似。

动态库存

淘宝秒杀天猫魔盒时,只有一个商品(行话叫SKU),库存是15000个。每有一人秒杀成功,库存就减1,19秒卖完,意味着每秒要成功产生789个订单(下订单的请求可能有8万个,只是举例说明,非实际数字,也可能是1万个)。想象一下,你在广场卖火车票,每秒有8万人举着钱喊着“卖给我”。

上过大学的人都知道,比秒小的时间单位有毫秒、皮秒、飞秒。但交易系统登记一笔交易可不像电子绕原子核运动那么简单,它要完成一系列操作:检查是否恶意访问、获取系统时间、获取顾客默认收货地址、核对顾客秒杀资格(当时规定是天猫T2、T3达人)、生成订单号、将顾客ID、系统时间、订单号、收货地址写入订单系统、扣除顾客天猫积分、减少商品库存、给顾客打标记(每人只能秒一个,下次不能再秒)等。每一项操作都需花费毫秒级的时间,这些操作加起来可能接近1秒。虽然淘宝服务器性能强悍,采用了分布式和集群技术,但结果也只是比1秒稍理想一些。即便有1万台服务器,也无法将这个时间缩短到万分之一秒,因为商品只有一种,库存对应的数据库记录只有一行,所有交易请求都要在此处理。

能否把15000个库存拆分成5000个商品,分配到5000台服务器上,让5000台服务器同时处理呢?答案是否定的。首先,5000个商品意味着有5000个商品详情页和5000个购买按钮,这对前期的营销和引流来说是灾难,基本无法设置引流入口,违背了商业管理原则,还增加了信息混乱程度。其次,天猫魔盒秒杀的交易额不大,即使按官方标价399元计算,也只有6百万的交易。若为这6百万交易投入如此大的配套成本,太不划算。再次,淘宝有十几亿商品,这些商品的展示、交易和管理本就分布在上万台服务器上,没必要再将每个商品按库存拆分。

这789人抢到商品后,不一定都会付款(用99积分换天猫魔盒还好,无需网银操作,成本低,大部分人会付款;但3999元秒杀iPhone 5S就不一定了,有人可能网银有问题,有人可能改变主意),这就带来了订单取消、重新恢复库存的问题。而且,想买的消费者会认为还有机会,会继续在前台刷新页面,最终这个秒杀活动会被热情的消费者持续刷新30秒到1分钟。

商品数据库

以北京西到深圳北的G71次高铁为例(这里只考虑南下方向,深圳北到北京西的G72车次是另一回事),它有17个站(北京西是01号站,深圳北是17号站),3种座位(商务、一等、二等)。表面看,这似乎只有3个商品:G71商务座、G71一等座、G71二等座。但很多轻易批评12306的技术人员(包括某些中等规模公司的专家、CTO)就在这里犯了第一个错误。

实际上,G71有136 * 3 = 408种商品(408个SKU),计算方法如下:

如果从北京西始发,有16种卖法(因为后面有16个站),北京西到保定、石家庄、郑州、武汉、长沙、广州、虎门、深圳等,每个都是独立的商品。同理,从石家庄上车,有15种下车的可能,以此类推,仅以上下车的站点计算,就有136种票:16 + 15 + 14 + … + 2 + 1 = 136。每种票又有3种座位,所以一共是408个商品。

下面看售票时如何减库存。由于商务、一等、二等三种座位数相互独立,库存操作也一样,下文不再考虑座位差异,只讨论出发与到达站。另外,这里说的是理论模型,并非12306数据库的实际设计。

旅客A买了一张北京西(01号站)到保定东(02号站)的票,【北京西到保定东】这个商品的库存要减1,同时,北京西到石家庄、郑州、武汉、长沙、广州、虎门、深圳等15个站台的商品库存也要减1。也就是说,卖出一张北京到保定东的票,实际上要减少16个商品的库存。

这还不是最复杂的。如果旅客B买了一张北京西(01号站)到深圳北(17号站)的票,除了【北京西到深圳北】这个商品的库存减1,北京西到保定东、石家庄、郑州、武汉、长沙、广州、虎门等15个站台的商品库存要减1,保定东到石家庄、郑州、武汉、长沙、广州、虎门、深圳北等15个站台的商品库存也要减1……总计要减少库存的商品数是16 + 15 + 14 + … + 1 = 120个。

当然,并非每张票的库存都完全实时计算。可以根据往年运营情况,在黄金周等高峰时段,预先对车票进行分配,比如增加北京到武汉的长途票,减少保定到石家庄的短途票。虽然我没有证据证明铁道部这样做了,但我相信,在12306网站出现之前,铁道部就有这种人工预分配的策略。

想象一下,8万人举着钱喊着“卖给我”。你好不容易从人群中拿到一个人的钱,却要转身找120个同事,让他们减少库存,而这120个同事也和你一样,被8万人围着,每卖出一个商品都要找几十个人减库存。这就是12306动态库存的复杂之处,比任何普通购物网站的库存机制复杂几十上百倍。

抢票插件

机器的速度永远比人快。当你好不容易从8万人中挤到柜台前,却发现来了10万根绑着钱的竹竿。有退票时,你要穿过三层人群才能接近柜台,而竹竿在8个人身后一伸,钱就到了柜台前。你低头看一眼手机,票就没了,而竹竿却一直伸着,不知疲倦。如果没有这10万根竹竿,你可能还是抢不到票,但不会像这样沮丧:“我怎么总是手最慢的那个!”

防止机器人抢票,并非简单地加个图片验证码就能解决。我曾写文章系统分析过,图片验证码有6种机器暴力破解方法,抢票插件用的是其中第三种——OCR识别。Google采用的Wave波形字母能较好地防范机器OCR,ems.com.cn上的验证码就是反面教材,机器OCR成功率接近100%,12306的图片验证码比ems的稍强。但验证码设置复杂了,有人会批评:这对大学生和办公室白领有利,农民工连26个字母都认不全,怎么办?采用动画验证码,又有人会说:视力不好的人怎么办?最后验证码设置得简单了,最高兴的却是开发抢票插件的公司。

就算采用机器完全无法识别的验证码,也防不住社会工程学的破解方法。招募一群网吧打游戏的青少年,每成功输入50个验证码给1块钱,或者等值的虚拟货币、游戏装备,我保证想赚这笔钱的人会很多。这点钱对于倒卖车票的利润来说,是可以接受的成本。有什么技术能防范社会工程学的破解方法呢?也许只有像【2克浓度为3%的U235在大亚湾核电站能发多少KW的电】这样的验证码才行。

没有历史包袱从零起步的交易系统?

前面的讨论是把12306当成和淘宝一样没有历史包袱、从零起步的交易系统,实际上并非如此。它背后的票池要服务电话售票、火车站售票、代售点售票等多个传统渠道。除了客运服务,12306还有全国最大(很可能也是全球最大)的大宗物资货运系统。

脱离政策(包括定价政策、警方打击黄牛政策、身份验证政策)谈技术,无法解决春运抢票难题。要想让春运时每个人在12306抢票都不拥挤(但不一定能抢到票,铁路运力有限),就相当于逼着12306购置大量服务器应对春运,春运过后,让它像amazon一样成为强大的云计算服务商,这和逼着北京修一条10车道的高速公路去八达岭长城是一个道理。

目前12306在技术上确实存在问题,比如抢票高峰时,输入身份证号和图片验证码都会卡顿(我亲身测试过),服务器端繁忙,浏览器端怎么会卡顿呢?

但12306在不断进步。相信2014年春运时,技术将不再是一票难求的主要原因。在铁路运力无法快速增加(孙中山先生计划的20万公里铁路,至今快70年才修到10万公里)的情况下,要实现春运公平购票,需要调整停靠政策。

解决方法

以下方法针对春节、国庆等高峰时期。其他时期,大部分线路维持现状即可,问题不大,极少数票源紧张的线路可按春运情况处理:

1. 拍卖法,价高者得

当硬座票拍出飞机票价格时,相信买票就不难了(可惜票价会很贵),黄牛也会减少。若说淘宝能帮12306解决技术问题,其拍卖系统可以发挥作用。浙江省高院在淘宝拍卖一年多,成交26亿。

可惜这个方法难以实行。现在高铁票价都被媒体和意见领袖批评,更别说拍卖了。而且,

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容