代码改变世界

【讨论】从技术角度分析铁路系统订票改进方案

2012-01-06 14:02  chris-shao  阅读(4416)  评论(34编辑  收藏  举报

 

针对铁路网站订票系统频繁的访问出错,无法订票问题,虽然很多讨论都是从制度,社会等方面做了分析,从技术角度是否能够完美解决呢?从技术方面分析该订票网站,可以看出,还是有很大的优化方案可以应用的。

 

下文只是根据自己的一些经验加上一些分析做如下方案,希望可以抛砖引玉吧,大家都来讨论下如果我们要做这样的一个系统,会如何进行系统的设计。

 

如果有分析不对的地方欢迎指证,但请勿恶言攻击。

 

优化一:前端优化

铁道部运输局的相关人士关于网站登陆难、提交订单过慢、余票无法查询等问题的解释称,是因为订票期间系统的访问量是平时的数十倍,导致出现异常。那么仅是由于这样的客观原因么?

打开订票网站首页查看网络请求:206.9 KB (112.2 KB 来自缓存),其中网页的请求只有9 KB(1.4 KB 来自缓存),JS:133 KB(81 KB 来自缓存),css:33.8 KB,图片:31.1 KB,另外网页中的CSS以及JS都未进行压缩,另外所有资源地址都是:dynamic.12306.cn,也就是说资源文件和程序文件都在一组服务器中,如果对这些信息进行压缩,那么至少可以减少50%的网络负载。另外,如果将资源文件分发到其他服务器中,并且使用CDN进行分发,打开网站的速度可以进一步优化。另外,当提交表单或刷新页面时,资源文件还需要多次加载,也进一步增加了网络访问。

优化二:排队机制

根据数据,今年春运预计2.35亿人次,日均588万,然而,目前铁路的春运客运能力仅为382万。根据这个运力来算,每天有200万人无法购买到春运车票属于正常现象。那么也就是说每天可购得票数为382万,那么假设高峰时段有一半190万在线购票,正常操作一个网页的频率为每分钟刷新一次,那么每秒服务器连接就在3.17万。按每个请求平均100K(优化后请求会降低),每秒流量在3.17G,那么,就需要一个庞大的服务器集群对这些流量进行分流。这里我建议可以考虑开发排队序列,就像在银行办理业务时的排队机一样,每个登录用户在购票前可以获得一个加密票据,这个票据在一台排队服务器中进行排序,按照业务处理能力,每次同时处理1000-1w个用户。当一个用户办理完成之后,后面的用户才可以进入购票通道。在购票通道中或者超时,或者完成购票正常结束任务。这样的情况下,就有效的控制了对中心数据库的访问,并且,排队者就有了时间观念,不会由于网站无法访问而懊恼。并且,还避免了秒杀性质的出票。

优化三:超时处理

如果采用了排队机制,那么就需要限制业务处理中的时间,否则就会造成排队过长,而实际在业务处理中的用户并未真正办理的情况,解决这个问题,需要考虑自动超时和强制超时两种方案,自动超时,可以在用户5分钟内没有响应,则认为用户已经不再购买,自动超时,另外,如果15分钟内未完成购票,则进行强制超时。

优化四:限制一次购买数量

限制一次购票数量,可以有效的避免刷票的行为,并且在不同的网络环境下,也提供了相同的购票几率。

优化五:明确退款机制

用户反映的购票支付成功后,无法拿到票的问题,这个是由于银行接口和网站接口这个调用是异步的,比如说用户在订票成功后转到了银行支付页面,然后在银行支付页面停留直到购票网站超时,然后支付,银行接口拿到了正确的支付凭证,所以还是会支付成功,但是当银行接口调用网站接口出票时,订单已经超时,就造成了已经交钱,无法拿到票的情况,解决这种情况,按目前的异步方式来看,是不可能的,因为不可能将付款与出票放入在同一个事务中(同时成功或者同时失败)。所以解决问题的方法就是延长支付时间,另外,对于支付成功但是未拿到票的用户进行合理的退款。

优化六:分级数据库集群

这个系统一个最大的难点在于所需要的数据均是实时数据,从而每次查询都需要尽量精确的数据,引入分级的数据库集群,可以按用户的查询需求进行划分,有部分用户查询是为了看是否有票,是否值得在网站等待,有的用户查询是为了购票,有的查询为了出票,根据这样的需求,查询是否有票的数据库可以适当延后,与中心数据库同步的频率可以适当降低,比如30分钟执行一次同步,其次,查询是否有票的数据库,就需要更加精确,比如可以1分钟执行一次同步。最后,在用户确定提交订票时,再连接中心数据库,处理订票逻辑。这样分级,降低中心数据库的访问次数,可以保证数据库的有效处理,另外,在中心数据库进行订票处理过程中,需要对数据进行行锁,以保证数据的正确。

优化七:只提供订票接口,开放网站API

参考飞机票购买方式,火车票也采用只提供API的方式,这样,大部分网站流量分流到合作网站上去,节约了成本,同时可以专心做核心逻辑。