也谈铁路订票系统的优化

[不指定 2012/01/17 12:10 | by ipaddr ]

近来诸多牛人在讨论12306.cn网站的优化,做为一名电商网站的技术人员,以及多次在12306.cn网站购票成功的IT人士,也参与大致分析一下。

网上传播较广的优化文章主要有两篇:
1. 云风同学设计的排队系统:  http://blog.codingnow.com/2012/01/ticket_queue.html
没细看,个人觉得这系统意义不大,解决不了关键问题,再牛B的排队系统,队伍排得再漂亮,没人插队,没人攻击,用户登录后,你提醒他前面还有8亿人在等待,再过2小时后来试试运气,照样骂声一片。当然适当运用队列系统来缓解后端压力,避免雪崩,也是可以参考的。(比如现在的12306,后端处理不过来,直接拒绝登录,让你在门外排队)

2. 陈皓同学的整站性能分析: http://www.udpwork.com/item/6708.html
对业务场景的分析很到位,12306.cn网站,与新闻门户,IM聊天工具,网游,微博业务完全不一样;根据CAP理论,后者由于对数据一致性要求不是很高,或者没有集中的数据资源,所以对数据做分区和平行扩展是容易很多很多的。另外,此文的结论也高度赞同。

这类电商网站具有很强的事务性,对数据一致性要求极高,不可能同一个座位卖给两个人,也不可能卖得超载,否则非在车上打起来不可。订单逻辑比淘宝之类的还要复杂一些,因为还有一个分配座位这个逻辑。

而且还有一个极其变态的规则:票是稀缺资源,不可能人手一张,只能靠抢;这就直接导致大家在放票的那段时间,全部登录到系统抢票,注定这类系统容易雪崩,系统设计时一定要考虑极端情况,在达到性能瓶颈时必须快速的丢掉一些用户请求,保证系统可用。

强事务的系统,数据层的分区设计和优化才是关键;
WEB层优化比较容易,js,css,image之类的使用常规的压缩、合并、客户端缓存、CDN分布,基本上没啥难度;
逻辑层也不复杂,不存在数据,可以很容易的平行扩展,但设计很关键;
数据层会是整个系统的性能瓶颈,因为最底层下订单时,必须会有锁表,可能在车次,或者是车箱级别锁表,下订单是串行的,这里没法并发。

以下简单讲一下核心业务逻辑(下订单)的一个优化思路。

主要有二个核心操作:
a. 查询车次
b. 下订单和分配座位

几个关键的数据:
1.库存表(余票信息)
2.订单表

数据库的优化:
1. 库存表
a. 数据按日期分区,因为前端入口是按日期来查询的,所以按日期分区是相当容易的。
b. 余票信息,分两张表:
     表A:  用来实时生成订单,这张表会锁表
     关键字段如下: 日期 | 车次 | 席别(坐,卧,无) | 余票数
     注意,这里同一个车次,将不同席别分成了多条记录,以避免单行锁表时,不影响其它席别的购票。可根据机器性能情况,按车次再进行数据分区。如果性能仍不能满足要求,可以再细分到车箱级别进行锁表。

     表B:  用于用户订票的第一个查询车次的页面,需要将表A的数据,定期同步过来,做些汇总给用户查询,这里的数据只读,并且可以复制N多份,数据量不大,可全内存化,以优化查询性能。
     关键字段如下:日期 | 车次 |坐余票数 |卧余票数| 无坐余票数
     注意,数据是旁路进程从表A同步过来的,非实时数据,同步粒度可以是秒级或分钟级,这地方没有实时数据的要求,因为这类系统库存信息变化太快,用户在第一个页面看到的库存,一定不等于下订单页面的库存。

2. 订单表

分两张表,分别为实时订单,以及取票订单表
     实时订单表:在下订单页面,只存在写操作,性能问题不大
     关键字段:日期 |证件号|车次 | 席别 | 数量(1)| 所属用户 | 其它信息
     注意:这里没有座位号信息,下订单时,不需要分配座位号


     取票订单表:用户支付成功后,由一个旁路进程(位置分配进程),将实时订单表的数据,按坐位分配规则,写入到这张表。为便于取票,可以按证件号将数据进行分区。
     关键字段: 日期 |证件号|车次 |席别 | 座位号

业务逻辑优化:

根据上面的表设计,基本可以看出业务如何实现了:
1. 查询车次页面:读余票B表,只读,可复制N份,平行扩展。
2. 下订单:根据用户请求,对余票A表进行锁表,行级锁,读出余票数,判断是否有余票,有的话,余票数减1,订票成功,写实时订单表。这地方千万不要去分配座位
3. 用户支付
4. 支付成功后,通知用户订票成功,后端进程再去分配座位。分配座位实时性要求不高,可以几小时后完成,发邮件或短信通知用户都OK。
5. 除此之外,以上逻辑没有考虑单个证件订多张票的问题,这个可以将订单A表的非实时数据,多复制几份进行查询。

经过以上优化,性能应该有很大提升,数据层也有了很大的平行扩展的能力了。

总结一下:

A.  经过以上调整,性能会有较大提升,但肯定还会有骂声,因为核心问题是票不够抢,假设10分钟内所有票都卖完了,估计没抢到的会骂娘,民工兄弟也会骂娘。
B.  不管骂声多大,铁老大开通网站卖票,并承诺不断改进,这绝对是一个进步
C.  核心问题是运力不足,如果车次能增加一倍的话,估计啥问题都解决了,也没人抢票了。(是车次增加一倍,不是铁轨增加一倍,要加强调度能力了)
D. 再深层点的原因,是地区发展不平衡导致,如果大家都在离家100公里内的地方工作,没必要这么折腾了。

分页: 1/1 第一页 1 最后页 [ 显示模式: 摘要 | 列表 ]