任何技术都离不开业务需求,因此,要说明性能问题,首先仍是想先说说业务问题。css
多说几句:html
我说那么多,我只是想从业务上告诉你们,咱们须要从业务上真正了解春运铁路订票这样业务的变态之处。前端
要解决性能的问题,有不少种经常使用的方法,我在下面列举一下,我相信12306这个网站使用下面的这些技术会让其性能有质的飞跃。nginx
1、前端负载均衡程序员
经过DNS的负载均衡器(通常在路由器上根据路由的负载重定向)能够把用户的访问均匀地分散在多个Web服务器上。这样能够减小Web服务器的请求负载。由于http的请求都是短做业,因此,能够经过很简单的负载均衡器来完成这一功能。最好是有CDN网络让用户链接与其最近的服务器(CDN一般伴随着分布式存储)。(关于负载均衡更为详细的说明见“后端的负载均衡”)ajax
2、减小前端连接数redis
我看了一下12306.cn,打开主页须要建60多个HTTP链接,车票预订页面则有70多个HTTP请求,如今的浏览器都是并发请求的。因此,只要有100万个用户,就会有6000万个连接,太多了。一个登陆查询页面就行了。把js打成一个文件,把css也打成一个文件,把图标也打成一个文件,用css分块展现。把连接数减到最低。算法
3、减小网页大小增长带宽数据库
这个世界不是哪一个公司都敢作图片服务的,由于图片太耗带宽了。如今宽带时代很难有人能体会到当拨号时代作个图页都不敢用图片的情形(如今在手机端浏览也是这个情形)。我查看了一下12306首页的须要下载的总文件大小大约在900KB左右,若是你访问过了,浏览器会帮你缓存不少,只需下载10K左右的文件。可是咱们能够想像一个极端一点的案例,1百万用户同时访问,且都是第一次访问,每人下载量须要1M,若是须要在120秒内返回,那么就须要,1M * 1M /120 * 8 = 66Gbps的带宽。很惊人吧。因此,我估计在当天,12306的阻塞基本上应该是网络带宽,因此,你可能看到的是没有响应。后面随着浏览器的缓存帮助12306减小不少带宽占用,因而负载一下就到了后端,后端的数据处理瓶颈一下就出来。因而你会看到不少http 500之类的错误。这说明服务器垮了。后端
4、前端页面静态化
静态化一些不觉变的页面和数据,并gzip一下。还有一个并态的方法是把这些静态页面放在/dev/shm下,这个目录就是内存,直接从内存中把文件读出来返回,这样能够减小昂贵的磁盘I/O。
5、优化查询
不少人查询都是在查同样的,彻底能够用反向代理合并这些并发的相同的查询。这样的技术主要用查询结果缓存来实现,第一次查询走数据库得到数据,并把数据放到缓存,后面的查询通通直接访问高速缓存。为每一个查询作Hash,使用NoSQL的技术能够完成这个优化。(这个技术也能够用作静态页面)
对于火车票量的查询,我的以为不要显示数字,就显示一个“有”或“无”就行了,这样能够大大简化系统复杂度,并提高性能。
6、缓存的问题
缓存能够用来缓存动态页面,也能够用来缓存查询的数据。缓存一般有那么几个问题:
1)缓存的更新。也叫缓存和数据库的同步。有这么几种方法,一是缓存time out,让缓存失效,重查,二是,由后端通知更新,一量后端发生变化,通知前端更新。前者实现起来比较简单,但实时性不高,后者实现起来比较复杂 ,但实时性高。
2)缓存的换页。内存可能不够,因此,须要把一些不活跃的数据换出内存,这个和操做系统的内存换页和交换内存很类似。FIFO、LRU、LFU都是比较经典的换页算法。相关内容参看Wikipeida的缓存算法。
3)缓存的重建和持久化。缓存在内存,系统总要维护,因此,缓存就会丢失,若是缓存没了,就须要重建,若是数据量很大,缓存重建的过程会很慢,这会影响生产环境,因此,缓存的持久化也是须要考虑的。
诸多强大的NoSQL都很好支持了上述三大缓存的问题。
前面讨论了前端性能的优化技术,因而前端可能就不是瓶颈问题了。那么性能问题就会到后端数据上来了。下面说几个后端常见的性能优化技术。
1、数据冗余
关于数据冗余,也就是说,把咱们的数据库的数据冗余处理,也就是减小表链接这样的开销比较大的操做,但这样会牺牲数据的一致性。风险比较大。不少人把NoSQL用作数据,快是快了,由于数据冗余了,但这对数据一致性有大的风险。这须要根据不一样的业务进行分析和处理。(注意:用关系型数据库很容易移植到NoSQL上,可是反过来从NoSQL到关系型就难了)
2、数据镜像
几乎全部主流的数据库都支持镜像,也就是replication。数据库的镜像带来的好处就是能够作负载均衡。把一台数据库的负载均分到多台上,同时又保证了数据一致性(Oracle的SCN)。最重要的是,这样还能够有高可用性,一台废了,还有另外一台在服务。
数据镜像的数据一致性多是个复杂的问题,因此咱们要在单条数据上进行数据分区,也就是说,把一个畅销商品的库存均分到不一样的服务器上,如,一个畅销商品有1万的库存,咱们能够设置10台服务器,每台服务器上有1000个库存,这就好像B2C的仓库同样。
3、数据分区
数据镜像不能解决的一个问题就是数据表里的记录太多,致使数据库操做太慢。因此,把数据分区。数据分区有不少种作法,通常来讲有下面这几种:
1)把数据把某种逻辑来分类。好比火车票的订票系统能够按各铁路局来分,可按各类车型分,能够按始发站分,能够按目的地分……,反正就是把一张表拆成多张有同样的字段可是不一样种类的表,这样,这些表就能够存在不一样的机器上以达到分担负载的目的。
2)把数据按字段分,也就是坚着分表。好比把一些不常常改的数据放在一个表里,常常改的数据放在另外多个表里。把一张表变成1对1的关系,这样,你能够减小表的字段个数,一样能够提高必定的性能。另外,字段多会形成一条记录的存储会被放到不一样的页表里,这对于读写性能都有问题。但这样一来会有不少复杂的控制。
3)平均分表。由于第一种方法是并不必定平均分均,可能某个种类的数据仍是不少。因此,也有采用平均分配的方式,经过主键ID的范围来分表。
4)同一数据分区。这个在上面数据镜像提过。也就是把同一商品的库存值分到不一样的服务器上,好比有10000个库存,能够分到10台服务器上,一台上有1000个库存。而后负载均衡。
这三种分区都有好有坏。最经常使用的仍是第一种。数据一旦分区,你就须要有一个或是多个调度来让你的前端程序知道去哪里找数据。把火车票的数据分区,并放在各个省市,会对12306这个系统有很是有意义的质的性能的提升。
4、后端系统负载均衡
前面说了数据分区,数据分区能够在必定程度上减轻负载,可是没法减轻热销商品的负载,对于火车票来讲,能够认为是大城市的某些主干线上的车票。这就须要使用数据镜像来减轻负载。使用数据镜像,你必然要使用负载均衡,在后端,咱们可能很难使用像路由器上的负载均衡器,由于那是均衡流量的,由于流量并不表明服务器的繁忙程度。所以,咱们须要一个任务分配系统,其还能监控各个服务器的负载状况。
任务分配服务器有一些难点:
我看到有不少系统都用静态的方式来分配,有的用hash,有的就简单地轮流分析。这些都不够好,一个是不能完美地负载均衡,另外一个静态的方法的致命缺陷是,若是有一台计算服务器死机了,或是咱们须要加入新的服务器,对于咱们的分配器来讲,都须要知道的。
还有一种方法是使用抢占式的方式进行负载均衡,由下游的计算服务器去任务服务器上拿任务。让这些计算服务器本身决定本身是否要任务。这样的好处是能够简化系统的复杂度,并且还能够任意实时地减小或增长计算服务器。可是惟一很差的就是,若是有一些任务只能在某种服务器上处理,这可能会引入一些复杂度。不过整体来讲,这种方法多是比较好的负载均衡。
5、异步、 throttle 和 批量处理
异步、throttle(节流阀) 和批量处理都须要对并发请求数作队列处理的。
因此,只要是异步,通常都会有throttle机制,通常都会有队列来排队,有队列,就会有持久化,而系统通常都会使用批量的方式来处理。
云风同窗设计的“排队系统” 就是这个技术。这和电子商务的订单系统很类似,就是说,个人系统收到了你的购票下单请求,可是我尚未真正处理,个人系统会跟据我本身的处理能力来throttle住这些大量的请求,并一点一点地处理。一旦处理完成,我就能够发邮件或短信告诉用户你来能够真正购票了。
在这里,我想经过业务和用户需求方面讨论一下云风同窗的这个排队系统,由于其从技术上看似解决了这个问题,可是从业务和用户需求上来讲可能仍是有一些值得咱们去深刻思考的地方:
1)队列的DoS攻击。首先,咱们思考一下,这个队是个单纯地排队的吗?这样作还不够好,由于这样咱们不能杜绝黄牛,并且单纯的ticket_id很容易发生DoS攻击,好比,我发起N个 ticket_id,进入购票流程后,我不买,我就耗你半个小时,很容易我就可让想买票的人几天都买不到票。有人说,用户应该要用身份证来排队, 这样在购买里就必须要用这个身份证来买,但这也还不能杜绝黄牛排队或是号贩子。由于他们能够注册N个账号来排队,但就是不买。黄牛这些人这个时候只须要干一个事,把网站搞得正常人不能访问,让用户只能经过他们来买。
2)对列的一致性?对这个队列的操做是否是须要锁?只要有锁,性能必定上不去。试想,100万我的同时要求你来分配位置号,这个队列将会成为性能瓶颈。你必定没有数据库实现得性能好,因此,可能比如今还差
3)队列的等待时间。购票时间半小时够不够?多很少?要是那时用户正好不能上网呢?若是时间短了,用户不够时间操做也会抱怨,若是时间长了,后面在排队的那些人也会抱怨。这个方法可能在实际操做上会有不少问题。另外,半个小时太长了,这彻底不现实,咱们用15分钟来举例:有1千万用户,每个时刻只能放进去1万个,这1万个用户须要15分钟完成全部操做,那么,这1千万用户所有处理完,须要1000*15m = 250小时,10天半,火车早开了。(我并不是乱说,根据铁道部专家的说明:这几天,平均一天下单100万,因此,处理1000万的用户须要十天。这个计算可能有点简单了,我只是想说,在这样低负载的系统下用排队可能都不能解决问题)
4)队列的分布式。这个排队系统只有一个队列好吗?还不足够好。由于,若是你放进去的能够购票的人若是在买同一个车次的一样的类型的票(好比某动车卧铺),仍是等于在抢票,也就是说系统的负载仍是会有可能集中到其中某台服务器上。所以,最好的方法是根据用户的需求——提供出发地和目的地,来对用户进行排队。而这样一来,队列也就能够是多个,只要是多个队列,就能够水平扩展了。
我以为彻底能够向网上购物学习。在排队(下单)的时候,收集好用户的信息和想要买的票,并容许用户设置购票的优先级,好比,A车次卧铺买 不到就买 B车次的卧铺,若是还买不到就买硬座等等,而后用户把所需的钱先充值好,接下来就是系统彻底自动地异步处理订单。成功不成功都发短信或邮件通知用户。这样,系统不只能够省去那半个小时的用户交互时间,自动化加快处理,还能够合并相同购票请求的人,进行批处理(减小数据库的操做次数)。这种方法最妙的事是能够知道这些排队用户的需求,不但能够优化用户的队列,把用户分布到不一样的队列,还能够像亚马逊的心愿单同样,让铁道部作车次统筹安排和调整(最后,排队系统(下单系统)仍是要保存在数据库里的或作持久化,不能只放在内存中,否则机器一down,就等着被骂吧)。
写了那么多,我小结一下:
0)不管你怎么设计,你的系统必定要能容易地水平扩展。也就是说,你的整个数据流中,全部的环节都要可以水平扩展。这样,当你的系统有性能问题时,“加3倍的服务器”才不会被人讥笑。
1)上述的技术不是一朝一夕能搞定的,没有长期的积累,基本无望。咱们能够看到,不管你用哪一种都会引起一些复杂性。
2)集中式的卖票很难搞定,使用上述的技术可让订票系统能有几佰倍的性能提高。而在各个省市建分站,分开卖票,是能让现有系统性能有质的提高的最好方法。
3)春运前夕抢票且票量供远小于求这种业务模式是至关变态的,让几千万甚至上亿的人在某个早晨的8点钟同时登陆同时抢票的这种业务模式是变态中的变态。业务形态的变态决定了不管他们怎么办干必定会被骂。
4)为了那么一两个星期而搞那么大的系统,而其它时间都在闲着,有些惋惜了,这也就是铁路才干得出来这样的事了。
评论区:
某只
2012年1月16日08:43 | #1
读完以为学到了很多东西,服务器优化也好,买票的心态也好
Zind
2012年1月16日08:50 | #2
云风的“排队系统”,连接 404 了
jimmy
2012年1月16日08:52 | #3
拜读了
rensn
2012年1月16日08:57 | #4
订票其实还有一个特色:各车次的分管铁路局是固定的!若是按铁路局将系统分割,负载将大大分散。就如10086.cn同样,他会要求你先输入手机号后跳转到各个分公司的系统。
Astar
2012年1月16日08:59 | #5
/system-analysis/20120116/317409.html
WRW
2012年1月16日09:00 | #6
很全面的分析,学习了。
imzrh
2012年1月16日09:11 | #7
好文章,让没有机会接触大型网络设计的我了解了很多东西。
“数据镜像的数据一致性多是个问题,因此咱们要吧在单条数据上进行数据分区”
感受这句不是很好读啊。而且”吧“是个错字吧。
haitao
2012年1月16日09:15 | #8
没提到把“选线路和支付彻底分开”,昨天铁道部本身也认可应该这么作。。。。。。。
http://blog.csdn.net/sz_haitao/article/details/7174037
另外,12306好像没有锁票的机制,因此出现大量的已支付却没买到票
陈皓
2012年1月16日09:31 | #9
你没有仔细看个人文章。我提到过的。在排队那一节。
biglazy
2012年1月16日09:25 | #10
“网游和QQ在线或是登陆时访问的更多的是用户本身的数据”,非游戏从业者,不过感受游戏里某些公共事件都是在读写公共资源,有时候规模也不小呢;不过副本技术确实极大的缩小了这个规模。
堕落天使
2012年1月16日09:32 | #11
空话。。。基本都是空话。。。
Terry Sun
2012年1月16日09:32 | #12
最后一句说的好. 真是苦了不能也不会上网的农民工兄弟了
Dem
2012年1月16日09:39 | #13
“如,一个畅销商品有1万的库存,咱们能够设置10台服务器,每台服务器上有100个库存,这就好像B2C的仓库同样。”应该是1000个库存吧,少了个0
liuxiaori
2012年1月16日09:41 | #14
信息量很足啊。文中提到能够使用缓存,好比如今12306是10分钟更新一次,缓存每10分钟都会失效,刷新缓存带来的峰值要怎么处理?
laneovcc
2012年1月16日09:45 | #15
用排队+配额申请制,
一句话update转换成insert操做, 非要说像的话, 这像个广告系统
forrest
2012年1月16日09:54 | #16
铁道部的放票模式不作更改,运力不提高,单靠优化网站仍是被骂。
假设铁道部有能力优化,那么能够预见,在很短的时间内,票就被卖出去了,没有买到票的人就会骂铁道部,票都被黄牛买了。
raymond
2012年1月16日09:54 | #17
星期一一大早就受教了,谢谢
buzzlight
2012年1月16日09:55 | #18
我以为须要注意一点火车票和电子商务的不一样,车次是有限的,不像淘宝这样商品无限多,并且业务逻辑简单得多。这样能够很容易的按照车次分区,每一个车次是单独的队列,甚至彻底能够放在内存,不一样车次间不存在锁的问题,即便同车次也能够优化锁粒度。另外,查询结果不必可刻意要求和实际票务状况同步一致,能够偏差一秒钟,查车次和查余票分开,这样90%的查询时能够缓存的。假设车票在开票10分钟内就被抢完, 根据每列车的座位数和每一个座位被卖的次数,能够估算每一个车次,每秒要处理几个请求,实际也没几个。
另外不一样于电子商务的库存,每一个座位能够被卖几回,用位运算实现很简单。
人们之因此用外挂刷票,由于网站烂,登录难,下单难,付款难等等,若是订票过程流畅,外挂天然就没人用了,再加上简单可靠的防刷新和限流措施,应付如今的量没问题,铁道部的数据不可信,看他们说他们处理的是世界顶尖的难题就知道。
绝望生鱼片
2012年1月16日09:56 | #19
一个次车。。一台服务器。。。
大麦头
2012年1月16日09:57 | #20
“1)占住库存,2)支付(可选),3)扣除库存的操做。” 请问博主您认为12306的订票环节,占住库存这个操做发生在哪一个步骤?
陈皓
2012年1月16日10:01 | #21
发生在你update数据库的时候。票量=票量-1的时候。
aaa
2012年1月16日10:10 | #22
技术方面不懂,不过我认为对于12306网站的库存管理,和普通B2C的电商库存管理,有不少不同的地方
1. 春运期间,运力不足,订单始终大于库存,但库存是固定的,即车票的最大限额。
2.闲暇时间,订单小于库存,但车次固定,座位固定,库存也是固定的,即使是一个乘客,也会开一班列车
铁道部几乎不用考虑订单和库存之间的供求关系,普通电商过于看重库存管理,是由于惧怕库存积压过多,直接影响到企业资金链的运行,而这个问题对于铁道部根本不存在,铁道部只要考虑怎么把固定的车票数量快速,流畅,均匀的分发到每位乘客手里就OK了。
并且我感受,这么多年应付春运的经验,铁道部对于减轻售票压力的方案也会很成熟的,不过确定都没有用在这个网站上面上。
haitao
2012年1月16日10:12 | #23
@buzzlight
由于无票了,用户不甘心,反复刷——访问压力大10倍
由于网页慢、死,因此用户不停的刷——访问压力大100倍
这是恶性循环:越是慢,访问量越大
若是,网页流畅了,哪怕仍是无票,就不存在这99倍的刷新了,而只是10倍的刷新
这是良性循环:越是快,访问量反而少了
bengxia
2012年1月16日10:15 | #24
带宽、CPU、存储都不是紧缺资源,一切的根源在于票太少人太多。一到春运运量能翻好几倍,运力只能提高一倍还不到。更好的系统是必须的,可是买不到票仍是挨骂。
一个能够考虑的办法是:限制300千米之内的短程票,分流到公路客运去,这样能够缓解一点点压力。
最好能依据统计分析来肯定:最小的瓶颈在哪。
但是,铁老大基本上是无视的,他们认为丫屁民老百姓就该受罪。
soxunyi
2012年1月16日10:18 | #25
查询和下单等操做用到的数据,应该是从铁道部客票系统已有的数据接口来直接获取数据。12306.cn和客票系统共享之前的老数据库。老旧的系统,必然适应不了如今的春运的变态需求。文中谈及的数据库优化的技术,目前来讲12306.cn无能为力。
大麦头
2012年1月16日10:23 | #26
陈皓 :
发生在你update数据库的时候。票量=票量-1的时候。
那么是否是隐含这个意思:针对某个车次有一条数据库记录用于登记剩余的车票,致使订购某车次的全部订单都要等待锁定这条记录而且更新?若是是这么设计的,确实有点那啥。通常来讲一个车次的票量有限,彻底能够用一个in memory的test-and-set(reduce)的操做来进行控制,热门车次的票量很快就会下降到零,后面的订单都test不过去,能够直接拒绝了。
陈皓
2012年1月16日10:27 | #27
并发下的数据一致性。放在内存里也同样要上锁作互斥。数据库本身原本也有缓存技术,其也是放在内存里的。
aqssxlzc
2012年1月16日10:29 | #28
我以为不少人没用过这个网站就来发表意见,这个网站虽然反复的提示用户太多稍后再试,但是绝对没有说挂掉或者慢的状况。只要登录进去,订单成功提交,后续过程基本没有页面慢死的状况。估计他是直接从请求中抽取一部分人登录来控制在线用户数量,而后再提交的订单中抽出一部分进入付款来控制售票速度。
大麦头
2012年1月16日10:33 | #29
陈皓 :
并发下的数据一致性。放在内存里也同样要上锁作互斥。数据库本身原本也有缓存技术,其也是放在内存里的。
(1)数据库锁不可怕,大量订单都要锁定同一资源才可怕
(2)用数据库的锁来作票量更新和统计,带上事务就要慢好几拍;若是这个票量更新要和每笔订单的事务合并提交,那就更要慢上N倍。
kino
2012年1月16日10:36 | #30
咱们都知道,铁道部不能知足全部人的要求,因此这样一个系统如何实现相对公平性,特别是此次对于电脑操做不会或较弱的人就不公平。
好比若是系统采用了排队系统后,不从技术角度考虑, 我这里还有几个问题想不通。
1. 何时开始排队,由于你们知道票是上午十点或下午三点出票。
这个队伍是一直存在,从系统运行时起。仍是天天从新排。
若是天天从新排,在重排的那一刻,还在系统里的人如何理?我想这里大部分人是踢出来,否则重排就没意义了。
若是队伍一直存在,进入的人是能够永远在里面,仍是有策略的踢出来。这里 永远在里面应该不可能。
若是有策略的踢出来,好比过一小时踢出来,那若是我要买的票在三点出票,我会想我要在两点多一点进入系统,
而买票的人应该都是这种想法,那我应该何时开始排队,才能保证我能在两点多一点进入系统,天哪,感受这个无解,绝望!
2. 假如队伍会在天天清空并在天天三点开始排队,但在排队的那一刻起,领到的号靠前的条件是什么?
应该是手速和网速。若是这样的话,咱们能够看看排在队伍前面的是些什么人:
程序刷的, 游戏高手, IT重业人员, 都市白领, 普通受过教育接触计算机的人 文化低(对应操做计算机的能力)的外来务工人员。
程序刷能够禁,但效果如何就不清楚了。
若是是这样的话,与现有系统比,不一样之处就在于
现有系统在人们试了无数次后,给人绝望
而排队后,一开始就给人绝望,你的号码是1000000,在你的前面还有999999人等待处理。
对于一个具体的会操做电脑的普通人而言:
现有系统:试了无数次,网页崩溃无数次,拼尽了耐心,终于买到了一张票。
排队系统: 放弃吧,你在这买不到票
若是开始排队算做比赛的话,那就是职业运动员和业余运动员的
固然,我绝对不是在说现有的系统好!我只是在说咱们全部的技术都做好了,仍是不能从业务角度实现它的合理公平性。
没事,瞎想的!
钢盅郭子
2012年1月16日10:36 | #31
把公款吃喝的钱省下来,够作 N 次春运订票模拟测试了,也就不难发现问题并解决了
wwwwwww
2012年1月16日10:40 | #32
“那么,这1千万用户所有处理完,须要1000*15m = 250小时,10天半,火车早开了。”
之前都是人工排队的时候, 春运又是如何处理过来的? 难道会是由于排队来不及, 而火车开着空车走的吗?
实际上, 我认为, 只须要把排队搬到网上来, 多开些窗口, 并使用一些防止黄牛刷队列的技术(这个方法能够有不少), 网络定票系统就够了, 其它都是多想.
aqssxlzc
2012年1月16日10:42 | #33
@kino
因此我以为正确的方法实际上是抽奖,在全部请求中抽奖,中奖的登录入系统,在全部订单请求中抽奖,中奖的进入支付。这样比排队系统公平不少,每一个订单都有中奖的机会。
wwwwwww
2012年1月16日10:47 | #34
云风的方案可靠就表如今把现实中的购火车票排队系统经过网络来实现, 效率确定要比现实排队高多了.
先排到队, 而后再查询, 再买票…总体火车购票系统的需求不就是这样吗?
另外, 负载小, 压力小, 实现简单靠谱.
陈皓
2012年1月16日10:54 | #35
不必定啊。只要不分站,不分布式,全局排队估计还不如现实中的排队。
wwwwwww
2012年1月16日11:02 | #36
你想的太复杂了, 典型的程序员思惟, 现实中的排队怎么会比网络队列高效呢? 就像云风说的, 排到队的, 每一个队列的后台用人工一对一服务都处理的过来…
@陈皓
invalid
2012年1月16日11:10 | #37
aqssxlzc :
我以为不少人没用过这个网站就来发表意见,这个网站虽然反复的提示用户太多稍后再试,但是绝对没有说挂掉或者慢的状况。只要登录进去,订单成功提交,后续过程基本没有页面慢死的状况。估计他是直接从请求中抽取一部分人登录来控制在线用户数量,而后再提交的订单中抽出一部分进入付款来控制售票速度。
也就是说……他们已经用了云风那种系统了,只是具体细节可能稍微不一样。
cc
2012年1月16日11:18 | #38
“集中式的卖票很难搞定,使用上述的技术可让订票系统能有几佰倍的性能提高。而在各个省市建分站,分开卖票,是能让现有系统性能有质的提高的最好方法。”
显然是忽悠不懂技术的,
cc
2012年1月16日11:22 | #39
文章中一堆”可能“,技术对比不够深刻,B2C,亚马逊,淘宝,QQ和网游。看标签云就能知道是研究啥的
陈皓
2012年1月16日11:30 | #40
@cc 期待你也写一篇。
M Jwo
2012年1月16日11:28 | #41
我认为铁道部的必定都知道上文的全部东西,由于我这样通常的人就知道了,也都会放进去考虑,个人系统正好是跨旧系统查询与追求效能,与铁道部需求很像,固然流量差不少。
我想主要的问题应该是当初估计尖峰流量是一亿,最后来了十亿,第二是后端系统承受不住,或是交换资料的部份承受不住,由于后端系统是内网旧系统,新旧系统沟通还要兼顾效能会有极大挑战,就算通常采用异步MQ等方式,可是量那么大可能也是吃不完,总不能下单后十小时才给结果。
不过这篇文章很值得想开发大系统的人去思考一下,我想仍是要通过这些问题的洗礼后天然就会了,我就是这样系统搞挂几回, PM下台几个就会了,反正怎么换也不会换掉技术人员。铁道部的人下次出来应该也都很强了,没有通过这些问题真的死过的,也没人会要你去设计这类的系统。
watchdb
2012年1月16日11:32 | #42
写的很是好,偶有空逐个了解下你写的每个技术,值得学习,致敬!!!
ivan
2012年1月16日11:38 | #43
网络购票跟大学的选课系统是否是差很少
ethan
2012年1月16日11:40 | #44
我看到的几点以下:
第一,从访问结果来看12306.cn已经使用了CDN网络,提供商名字忘记了,能够查出来
第二,从访问动态页面的结果看,12306.cn用的应该是ngnix+Jboss
第三,12306.cn和奥运订票系统同样由太极集团制做
第四,从访问结果看CDN基本上没出什么问题,每次500都是由Jboss返回的。我的理解,是jboss挂了
joylnwang
2012年1月16日11:44 | #45
分析的很全面,学习了。
M Jwo
2012年1月16日11:46 | #46
@M Jwo
补充,那么多人用hibernate的甚至EJB,这样的系统这类O/RM的个人经验是挡不住的,仍是直接弄memcache/Coherence, 資料庫用 partition table等比较稳
abadcafe
2012年1月16日12:05 | #47
楼主最后提出的方案,技术上是最好的,但政治上有风险…
想一想看, 铁道部已经被说成”最大的黄牛”多少年了, 若是搞成这种订单延迟处理的方式, 确定会被说成”黑幕”放票…
七剑下厨房
2012年1月16日12:05 | #48
大麦头 :
陈皓 :
并发下的数据一致性。放在内存里也同样要上锁作互斥。数据库本身原本也有缓存技术,其也是放在内存里的。(1)数据库锁不可怕,大量订单都要锁定同一资源才可怕
(2)用数据库的锁来作票量更新和统计,带上事务就要慢好几拍;若是这个票量更新要和每笔订单的事务合并提交,那就更要慢上N倍。
前两天翻了一下你们的评价,如今最大的瓶颈是 提交订单很是慢,很是困难,其次是支付接口常常出问题;登陆和查询不是那么紧。
提交订单瓶颈的缘由我估计是,铁路内部采用了网络支付限制,大约是1万张(忘记从哪里看到的),可是可能同时就是n多人同时抢票,这样,客观形成了一个排队效应;排在后面的人还要等前面的人去支付,再去更新数据库,把事务加到里面了,那是至关慢。
解决问题的首要一步是肯定这个系统达到什么效果,铁道部定时发票的节奏是不可能改变的,那套数据库也是不可能改变的,支付银行你也是没办法去改变的。僧多粥少,刷票也是不可避免的,你也不可能作到人人上去就能买到票。这个系统建设的目的就是,用户能快速登陆,查询,若是有票可以很快买到,或者很快被告知不被买到,并且可以避免黄牛。那么,这个系统就是成功的。
反过来看看,如今的网站呢?用户没法感知是否成功,明明看了有票就是提交不上,提交上了半天不响应,而后说不让你买了,好不容易买了交了钱了,支付那边又超时了。
因此说,我对12306的想法是:
1.找个好的产品经理,像用户看到票有而后就是提交不上去,一点其余可供感知的东西都没有,这种设计水平我就不说了;
2.优化网络流程,例如能够把网络支付作到网站里,或者彻底是异步支付;网络放票,能够作成按片不定时放,上午放上海,下午放杭州,随机放票,避免形成过多的并发;
3.再就是作好负载均衡,共享数据信息之类。其实我以为查询之类的能够用阿里云之类的来搞定啊,春运期间,搞定核心数据流程就OK了。
buzlight
2012年1月16日12:09 | #49
按车次作服务分区不必定每一个车次建一个数据库,memory或者redis均可以,座位号是key,每一个座位用bit集合标示某一站有没有卖。利用redis的原子操做,比数据库简单并且高效 @绝望生鱼片
Fenng
2012年1月16日12:22 | #50
1. Tim会接任Apple的CEO了,由于他搞定了苹果的库存问题
这个彻底是两回事.
2.集中在早8点到10点,每秒PV在高峰时上千万
这个数字有问题
3.去年双11节,淘宝的每小时的订单数大约在60万左右
错,淘宝峰值是278万笔/小时
4. 淘宝要比B2C的网站要简单得多,由于没有仓库
这个是臆测。复杂度同样的。
5. 数据镜像
至少对于Oracle来讲,目前没法作到有效的镜像,镜像更可能是为了数据安全可靠
6. 数据一致性才是真正的性能瓶颈
数据一致性并不是业务难题,并发能力支撑才是难题
陈皓
2012年1月16日13:11 | #51
1)我读的是乔布斯传里的说法。
2)关于峰值,愿闻其详。
3)峰值278万没有问题,我仍是说,淘宝的系统比较简单,由于没有他库。不过淘宝当时已经在极限上了,准备关一些省市流量了。
4)看来你不知仓库的压力。复杂度彻底不同。这点你外行了。
5)数据镜像有便可以保持负载也但是为了高可用性。
6)数据一致性是很耗性能的,并发的的难点是操做那些共享的数据,这你应该知道啊。
谢谢你的回复,不过没有看到你的思考哦。呵呵。
sarstime
2012年1月16日12:31 | #52
琢磨着这两天博主就会讨论这个热点问题,结果今天就看到了。 还有一部分业务是关于退票和改签的, 能够搞一个退票,改签票的提醒机制,好比注册到一个排队队列,若是有退,改签的票出来,就能够发个短信提醒队列里的人。
pooch
2012年1月16日12:36 | #53
“而在各个省市建分站,分开卖票,是能让现有系统性能有质的提高的最好方法。”
能详细说说这个数据切分方案吗?我的感受按省市很难分啊,由于火车是途径各省市的,不是各省市固定票额啊。
好比一趟北京始发,西安终点的车,若是在北京卖出了一张北京到郑州的某座位车票,那么这个座位接下来只能从郑州以西开始卖了,因此在郑州买票的时候,就要去查在以前的站到底卖出了哪些车票,区间是怎么样的。
我的以为,12306自己就应该是做为一个终端接入铁路原有购票系统,本质上来讲,和窗口,电话处于同一位置,都须要去中心查询,下单,但网站的特殊性带来了麻烦,不像窗口——有排队,电话——超出服务能够占线,上述2种均可以控制住流量,至少不会引发自身的崩溃。而对于网站,通常的状况都应该提供7*24的服务,频频不能提供服务,天然会引来不少骂声。
对于铁道部来讲,如今若是去改造原有购票系统,牵扯面感受比较广,先不说开发成本,光是回归窗口和电话业务估计就须要半年。因此,只能好好改造12306了
mikespook
2012年1月16日12:37 | #54
有些例证确实值得商榷,不过既然是务虚,那就更虚一点吧~~~
让 CAP 来套用一下这个系统吧。
cafe猫
2012年1月16日13:04 | #55
这个世界任何事物都是相对的。有阴就有样。一样,有排队的地方就有黄牛,排队和黄牛是两个对立相生的。我以为。铁道部花那么大力气去搞个订票网站,很不免有刷票,外挂什么的。并且对那么大的高并发访问需求,还要注意锁定资源,支付什么的。这是给本身找难题。
为何不这样?铁道部就只管开放查询,订票,退票的接口。把接口开放出来,给其余的B2C,好比淘宝,京东,易讯什么的有经验的电商。而后。铁道部严格把关有订票资格的网站,只让有资格的电商或代理商才能访问接口?
个人思路就是开放! 尽可能把难题开放出去。只要把握住关键的就好了。
无限
2012年1月16日13:09 | #56
一些想法,欢迎斧正
1. 春运的火车票就固定的那么多,并不会像作b2c那样不断的涌进来新的商品,因此总的查询虽然多,实际上是能够划分红许多相互之间没有联系的小查询的,好比想坐某个车次的几十万或者几百万人在查询某车次的。
2. 数据一致性也不是问题,春运这个票量全放内存里并不大,能够考虑采用redis集群模式,实时同步写操做到各个cluster去,因此能够保证每一个agent服务那的数据也是即时的。
3. 不显示票数而显示有或无,这个技术上当然好,不过考虑到天朝的官府公信力,若是只显示有或无,恐怕会引发更大的怀疑,搞不到票的人有可能闹事,网民也会起哄,因此最好仍是显示票数,非可是显示票数,最好是哪一个身份证买的都显示出来,这样才能消铒民怨。
4, 我却是以为春运这种暴增的任务能够考虑出动飞艇运输,参加博文 http://geek42.info/article/enhancement-of-beijing-traffic.rst
jiacheo
2012年1月16日13:14 | #1
Fenng :
1. Tim会接任Apple的CEO了,由于他搞定了苹果的库存问题
这个彻底是两回事.
2.集中在早8点到10点,每秒PV在高峰时上千万
这个数字有问题
3.去年双11节,淘宝的每小时的订单数大约在60万左右
错,淘宝峰值是278万笔/小时
4. 淘宝要比B2C的网站要简单得多,由于没有仓库
这个是臆测。复杂度同样的。
5. 数据镜像
至少对于Oracle来讲,目前没法作到有效的镜像,镜像更可能是为了数据安全可靠
6. 数据一致性才是真正的性能瓶颈
数据一致性并不是业务难题,并发能力支撑才是难题
仍是冯大辉老师说的实在. 为了突出系统复杂性, 把其余的业务看得太简单了.
Johnny
2012年1月16日13:23 | #2
1. 12306其实并非那么烂,12306高峰期的表现跟加三倍服务器的京东比仍是要好很多的,淘宝那次1元卖支付宝宝令的时候,挂的比12306还难看。
2. Redis、分表分库、排队队列什么的,这些东西知道是作什么的是一回事,敢用到线上去另外一回事,特别是这么大的压力,淘宝为了去O,去小型机而投入的研发力量以及积累下来的经验,我相信比12306的合同还要贵的吧。并且这些东西解决的问题对于一个不差钱的主来讲其实也算不了什么大问题。
3. 12306若是真的只用了几千万的话,说实话真的不算贵,建一千米高铁花的钱都比这要多。
4. 看到一帮子人骂来骂去的,看到不少人的评论内容,感受有些人的水平可能还不如12306的开发人员。
5. 12306有了总比没有好,并且身边不少人包括我本身确实在上面买到了票,虽然刷了无数次才登进去,这已是一种进步了,但是仍是不少人在喷,咱们部门喷的最厉害的两人,一个是坐飞机回家的,一个是坐汽车回家的,他们都是“听别人说买不到票”,这个怎么回事呢。
NinGoo
2012年1月16日13:26 | #3
3)峰值278万没有问题,我仍是说了,淘宝的系统比较简单,由于没有他库。不过淘宝当时已经在极限上了,准备关一些省市流量了。
流量和交易系统的支撑量是两码事,100亿pv刷页面,10亿pv下单,能是一回事么,呵呵。没有仓库,库存仍是同样要减的,不然超卖就能够搞死任何一个活动了。
作技术的,写技术分析文章,仍是不要以道听途说来臆测的好。
NinGoo
2012年1月16日13:27 | #4
NinGoo :
3)峰值278万没有问题,我仍是说了,淘宝的系统比较简单,由于没有他库。不过淘宝当时已经在极限上了,准备关一些省市流量了。
流量和交易系统的支撑量是两码事,100亿pv刷页面,10亿pv下单,能是一回事么,呵呵。没有仓库,库存仍是同样要减的,不然超卖就能够搞死任何一个活动了。
作技术的,写技术分析文章,仍是不要以道听途说来臆测的好。
10亿pv刷页面,10亿pv下单,很差意思,多敲了个0,哈哈
陈皓
2012年1月16日13:30 | #5
我就知道最终会在这些细节上有人较真。你远远不明白,几个集中的物理仓库,和各个商户各自的库他的差异。你也就没法理解我说的。
耗子
2012年1月16日13:32 | #6
我以为,后台用纯C写cgi,前台用ajax减小整张html返回,配合上述的措施,应该会好不少的。
啄米鸟
2012年1月16日13:33 | #7
官方不是说IBM有解决办法而他们并无采纳么,因此问题仍是在领导层,不是技术层。
Gil
2012年1月16日13:56 | #8
1. 不少时候没法登录系统, 我在想这个跟外挂有没有关系, 毕竟一个外挂等于不少人同时登陆. 写这个外挂的人该拉出去毙了.
2. 订单提交比较慢. 这个其实若是真的按照车次来分的话, 彷佛数据一致的状况不会那么糟糕. 固然系统怎么设计的不清楚, 表级锁仍是行级锁不清楚, 或许只是一个作全局统计的地方存在瓶颈. 这个要详细trouble shooting.
别的地方彷佛没以为有多少很差的地方, 这个网站能够打分60分了.
其实, 在社会供给不足的状况下, 仍是计划经济, 配给制发票吧. 我们作不到每一个人都有票, 何须让这么多人耗时耗力的争夺呢. 干脆铁道部就提供一个预订系统, 提早一个月提交预订信息, 分级: 例如先保证老人, 儿童, 残疾人, 学生, 按照优先等级来分配, 咱们这些年轻人就不要去争夺了. 最后分到票的坐火车, 没有票的本身想办法.
Gil
2012年1月16日13:57 | #9
@啄米鸟 我以为若是IBM出方案, 仍是让咱们本身的公司来解决这个问题吧.
Shawnone
2012年1月16日14:03 | #10
后台提升性能的,关于技术方向有不少资料,但最关键的仍是怎样和业务需求结合。我以为业务中还漏了重要的一点 – 席位复用。这个对排队,数据一致性等技术都会形成影响。也是和电子商务的订单系统的一个很大不一样。
Allen
2012年1月16日14:16 | #11
@kino
我以为前面若是有几十万人我以为不算问题,还有队伍确定在必定的时候是要清空的,一直排着也不符合常理,之前没12306的时候不也是天天早上清空一次吗?
对变态的业务逻辑只能用变态的业务模型来知足。票(大学)是稀缺资源,不够是正常的。可是只看到有人报怨本身没考好,没报好,没人有抱怨志愿填报不合理。
固然咱们用不着让买票人也去参加考试而后凭分数来排定买票的排队次序。在互联网售票已经能够开始运做(虽然运做的还不完美),咱们就把排队的广场放在网络上吧。
春运期间售票若是能改为如下流程我以为12306将能知足广大票友的需求
售票分为如下几个阶段:
实名注册期 => 需求收集期 => 秒杀抢票期 => 后台卖票期 => 订单确认付款期 => 取票\刷卡上车期
假定某年春运第一天为1月30号,提早10天(20号)能够拿票来看
10号(所购票前20天12306开放购票意向收集与用户注册),相似大学报志愿同样,每身份证限购五张,可提交最多所购票当天6个不一样车次购票请求,购票请求按优先级从上到下将会在后台售票时依次尝试知足
18号零点前为购票需求收集截止期。
18号早上9点开始开放抢票,用户保持已登陆状态开始抢位置,系统显示当前排队的位置,刷新没用,越刷越日后排,一次点击就够了!!19号零点前抢票结束 –您要是实在不着急买票,能够等到最后一秒再来抢,不过买不到票您可别怨铁道路
19号零点后台运行卖票程序,按照18号抢票排队的顺序卖票依次处理售票,售一张则发一个邮件与短信确认,24小时内需确认,逾期则收回。–固然,若是您请票心切,提早把钱存到12306的我的购票帐号里也行,铁道部恨不得您在那能存些余额呢。
20号可拿到纸票,或付款后便可以在铁道部数据库中查到购票记录可届时刷卡上车
比方说某人今天网速不佳,或选的车次都太热门没买到票,那好,今天没买到30号出发的票,我再修改一下个人车次信息,明天早上9点我再换个网速好点的地方再去抢个好位置,说不定明天他就能如愿买到31的票。
这个方案有两个“亮”点:
1)抢票。不抢是不行的,中国人这么多,资源又那么少,铁道运力有限的状况下你能不抢??你不在网上刷网页抢,就得冬天一大早起来排队去抢,或者打电话抢,你选择怎么抢??
2)后台卖票程序。这个比起什么高并发,数据库瓶颈,多台server,数据库一致性等等问题简单到不知道哪里去了。后台卖票程序运行的时候定在晚上0点到早上7点之间,7个小时其它地方不卖票,光这个程序读数据库中收集好的购票意向信息逐个处理,7个小时处理不完接下来一天的购票信息吗?若是真处理不完那么具体细节设计上咱们再好好探讨一下
排队系统是从云风那里读到的。事在人为,若是不人为设置障碍或者铁道部本身就没打算好好卖,票绝对没有那么难卖
奇石
2012年1月16日14:40 | #12
我以为问题在于领导,固然了12360的技术人员也都是垃圾。
1. 一个订票的热点网页,能作出800K大小,须要几十个链接,这彻底不可容忍的。若是谁说这均可以容忍,那你不配当程序员。
2. 订票为什么必定要抢?难道不能够以1个小时,或者是1天为一个周期,进行抽签?每一个周期,你们随时选票,而后进行抽签,这样即保证了公平性,又能够不用把网站搞垮。
3. 关于建分站的问题,这个本文做者纯属瞎扯淡。各省创建分站,结果是各个省份自制,且不说制度很乱,并且效果也不会好。由于创建单一的购买渠道,在这个渠道处也能够进行分流,何须让个省市去作?并且,从资源利用率来讲,单一的网站能够更合理的利用资源。
4. 我以为若是有现有的云计算服务能够用的话,铁道部不该该本身从服务器作起。由于第一,你无法作的比别人更好,第二,你作这么个东西,只是那么几天使用,不值得。若是不信任商业公司,能够签定保密协议,若是泄密,重重地处罚。
NinGoo
2012年1月16日14:44 | #13
陈皓 :
我就知道最终会在这些细节上有人较真。你远远不明白,几个集中的物理仓库,和各个商户各自的库他的差异。你也就不管理解我说的。
不是非要和你在细节上较真,可是作技术的,不较真细节来谈架构就是扯淡。就跟你说“集中在早8点到10点,每秒PV在高峰时上千万。”,我不清楚这能持续多少秒?若是持续一分钟,不就6亿pv没了?那一天14亿pv都集中到这几秒了吧。
仓库库存管理和调度确实是难度,我认可我不懂,因此我也没法去评论说12306或者京东在这一块容易仍是难。若是把仓库库存管理调度和下单系统彻底耦合在一块儿设计,那确实是难度很是高的问题。
一个业务,难仍是容易,从不一样的角度去看多是不同的,若是你先假设了难,而后找论点来支撑,那怎么都是难的。若是先假设了容易,找论点来支撑,发现又没有那么难了。因此辩论难仍是易,是很相互说服的。各自的经验会得出不同的结果。
12306的pv,有多少部分是在刷登陆的?有多少pv是在刷票务信息的?有多少在刷下单的?有多少在刷支付的?不要看到14亿就想固然的认为交易系统压力大,就是高并发交易。我没有作过火车票交易系统,但从机票系统来看,压力基本都集中在搜索票务信息上,真正的下单压力其实不大。各机票代理都要从中航信去获取票务信息,这方面提及来比12306本身一家人来作的难度更大了。
真想给12306平反或者支招,仍是多找些数据,多作些研究,别随便百度一把出来几个数字就引用为论据,像你的博客关于里说不到45岁不写书,我想是一个道理的。
陈皓
2012年1月16日15:20 | #14
1)高峰时段意思是一个尖,不是持续。
2)仓库是集中管理的,这个和车票是同样的。淘宝的库存分担到了每一个商户身上。是我没说清?
3)在放票的时候,12306的有多少人登陆,就有多少人查询,就有多少人下单。这是刚需,和上网买东西不同。难道这也很难理解?
4)机票的业务能和火车票这种比吗?能作飞机的人原本就少,并且机票整年能够买。代理公司或是旅行团,一次订N张票,批量操做。
不是我说不清楚,是你必定要挑刺罢了。我没有给12306支招,我谈的是高性能的技术。你的理解能力须要提升。
利物浦的亨德森
2012年1月16日14:48 | #15
学生已是提早了。通常高校都会提早20多天通知回家的学生订票的。主要是硬座票。可是学生里面仍是有部分车次是很难弄到票的。主要是山东和四川。这说明即便是划出一个小部分人群来,在相对集中的几天内,铁道部的运力仍是不足。做为学生我知道这个。
老人和残疾人人数较少,并且有相关的证实文件,确实能够。
儿童就很差说了,至少在目前来讲儿童缺少像身份证同样的证实去保证系统可以识别这个用户就是个儿童。这个可能须要医院,公安局等多个部门共同改革才可能。重点是家长会放心儿童一人上车????即便可以证实了。这也是个问题。
固然配额制的话,在供给有限的状况下,那就是巨大的寻租和腐败的空间了。谁先拿票,谁不拿票?即便有个评估标准,不说执行状况和评估所须要花费的资金和人力成本了。那也须要一个十分信息公开透明的机制和设计去保障,至少在目前来讲尚未哪一个政府部门作到。估计等到财政预算公开的那天,这个就实现了。。。。。因此一旦配额,那就是超级黄牛的时代了。
因此我的认为仍是回到经济学的基本框架中来。
(1)提升运力,同时创建灵活的火车时刻表。这个就是增长供给。具体数据不是很清楚,可是春运这十几天确定是峰值,不过平时又没那么多人。若是简单的堆车皮,平时的运营成本过高。因此火车的发车和订价机制就要放开。经过灵活的车次和价格来引导平常需求和下降运营成本。固然一方面要保证天天都有到其余地方的车,同时还要保证低成本,少空车,这个我以为是一个较复杂的优化问题。重点是买车容易,修路难。提升运力修铁路须要时间。。。。。。
(2)错峰放假。这个就是减小需求。核心的假期就是除夕及以后的三天。你们都集中在这个时候,必然有搞不到票的。加上学生假期也是那个时候。因此能够考虑规定春节前10天和后10天不出售学生票。让学生的需求在高峰期
前消化掉。至于其余行业的。老板们行行好,别死拉着员工非得等到春节前两天才让回了吧。。。。
@Gil
mdqyz
2012年1月16日14:57 | #16
其实12306不是什么“订票”系统,而是“购票”系统,因此才有那么多同步问题,由于你必须去“抢”当前放出来的那点票,而不能“订”将来放出来的票,也不支持模糊的订票需求。
另外,余票查询,车次查询等等都不该该是数据库同步的,因此实际上同步的只有“占库存”这个操做,但也能够设计成把需求放入按每日车次的队列,先完成支付的先得,异步处理队列再通知用户就能够了。这样基本上就没有用户能够参与的同步事件,准备好足够的服务器就能够解决全人类的订票要求了吧。
bones7456
2012年1月16日15:09 | #17
@Fenng
278w实际上是平均值,双十一的峰值接近500w。而双十二的0点这一小时,成交笔数超过650w。
2012年1月16日16:17 | #20
1:数据层:高并发下对数据存取的压力经过分区化来实现,扩展性由读远大于写的特性则增长copy来处理读请求,数据一致性就用单写来保证。 2:业务逻辑上:只要放票方式是如此,必然带来购票人群在放票瞬间的高峰涌入,除非已经作好系统负载能力等于峰值的准备,不然只能经过削峰的形式处理,好比排队系统。 3:支持大辉的前5点,第六点实际上说的跟陈皓说的差很少是一码事,平行扩展的时候在保证可用性的前提下,并发能力的提升须要经过增长数据的copy来实现,同步报文丢失的可能性增大,一致性就会受到影响,强制保证一致性必然带来并发能力的降低,不知道我对CAP的理解对不对…