`
myreligion
  • 浏览: 205155 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

对于12306,我的完整技术方案

    博客分类:
  • Java
 
阅读更多
12306主要就是卖票比较复杂,注册登录之类的功能就不说了。

有网友说,12306卖票系统比航空复杂,因为要分段卖,航空只有起点和终点,火车中间还有好多站。不过好消息是,这些站在售票时是连续的,不会出现1张票跳着站买的情况,这样就可以把一张票拆成N张只有起点和终点的票,和航空售票一样了。(我不了解航空售票,也不了解火车售票业务具体模型,下面都是基于推测和假设之类的。)

卖票分为两部分,查询和购买。12306目前提供了单独的查询,我觉得这个其实挺好的,至少有读写分离的思想;不过延迟10分钟的数据,肯定没什么人愿意用,大家还是要挤进购买系统查询。单独的查询相当于摆设了,没有发挥作用。要让查询系统有效,尤其是春运期间,延迟应该在30秒之内。

查询剩余票数设计:

查询的特点是按照车次信息或者时间查,车次和时间一般都不会变,因此在设计时,可以把页面分成两部分。一是匹配的车次列表信息,如北京到上海有哪些车,这个结果可以用CDN缓存。车次基本是固定的,缓存设置为10分钟应该就能满足需要。不占用负载。在浏览器拿到这个页面后,通过异步请求,根据每趟车的编号二次查询剩余票数等实时数据,合并显示。

车次查询时,把车次信息分库存储,并作冗余存储。好比这个库提供所有北京->xxx的查询,这个库提供上海到xxx的查询,这个库提供广州到xx的查询,剩下的在一个大库中等。车次变化很小,库可以分散存,而且可以冗余存储。用内存表也行,总数据量也不多,性能上没什么可说的。

对于实时票数,确实是比较困难的,网上很多方案都不对,没有考虑中间站的问题。剩余票数缓存并不好做。我的想法是,提前分好票,然后用单独的数据结构做缓存。

例如,对于G113高铁,共有8站:北京、德州、济南、徐州、南京、常州、苏州、上海。假设它有两千张票,座位啊卧铺啊啥的。在发票前,创建新表20120113_G113,然后把2000张票提前插入到表中,每个票都有一个本表内唯一的数字编号。表结构基本上就是:编号、起始站、终点站、座位类型、车厢、座位号、乘客姓名、乘客证件号码、车票状态等实际业务模型需要。初始化时,起点站就是北京(根据顺序存储为1),终点站就是上海(根据顺序存储为8),乘客信息空着表示尚未绑定乘客,车票状态置为“待出售”。

这样我们要查询2012年1月13号G113 济南->南京 的剩余票数时,就查询20120113_G113起始站编号大于等于3并且小于等于5,并且状态为“待出售”的记录数就行了。

每张表2000条数据,对于非春运时节,性能完全足够。对于春运时节,非繁忙路段,性能应该也足够了。对于春运繁忙期,继续看下面的。

车票出售基本流程:

用户选择车票并要求购买,系统锁定票并标记状态为“锁定中”,让用户付款等。完成后标记车票为“已经发售”,并且更新用户信息到车票的持有人信息字段中。此票不再出售。

对于中间站购票,假设用户购买了 济南->南京 ,前面流程不变。但完成出票后,将车票起始和终点站改为“济南”和“南京”,并且自动插入两张新票可用。一张是“北京->济南”,一张是“南京->上海”,通知队列更新相关缓存。相当于车票做了自动分裂。这样我们设计时只需要把一张票设计为“只有起点和终点”就行了。

更高效的剩余票数查询设计:

数据库的count操作并不快,因此对于繁忙季节的繁忙表,每次都count是铁定不行的。我想到的一个办法是:把上面提到的预售车票表加载到内存中。我们用一个64位long类型数字表示一张车票,每趟车的每种座位类型是一个long数组。

对于每个long数字,前面的32位用来顺序存储32个车站(假设一趟车最多有32个站,没查过,不行可以放长点),每一位标记“车票是否包含此站”。如G113 济南到南京的票(车站顺序为第3到第5站),long数字的第2到第4位设置为1,其他前32位设置为0。后面的32位用来表示车票在车票出售表中的唯一编号。这样根据一个long类型数字,我们就能表述一张票的发售信息了。

比如2012年1月13号G113,有软卧500张和硬卧1500张。那就需要两个数组。20120113_G113_软卧 对应一个长度500的long数组;20120113_G113_硬卧 对应一个长度1500的long数组。存储所有售票信息。

有点类似BitSet的感觉,对空间要求不高。我们可以做个系统把所有车票信息按照这种结构加载到内存中。对于实时查票,如查询2012年1月13号G113车次 济南->南京 的余票,就是遍历两个数组,检查位数为2和4的long数字有多少个,就直接获得了软卧和硬卧的剩余票数。对于现代计算机,这点遍历,时间是纳秒级的。

当车票被出售后,从long数组中删除票信息,比如先置为-1表示已经无效。再用后台线程实际删除(避免写冲突,将删除延迟到重建一个数组所消耗的多少纳秒内刚好没有写请求的时间段中)。如果long数组长度为0,那就是没有车票了,直接返回0;用户再怎么刷,也不会干扰数据库。

更高效的剩余票数查询方案的扩展性和容错性:

本身车票是按照车次划分的,同时也有时间维度,横向扩展不存在任何问题。

long数组可以根据数据库票务信息重新构造,而且成本不高(一条“select * from xxx where 状态=待发售” SQL语句)。在硬件故障,扩容机器,或是发现数据不一致时,重新构造数组就行。而且可以从后台异步做。扩展性和容错性都不是问题。

售票交易与锁票:

用户查询到有票后,填写要购买的票数,提交。好比购买两张硬卧,流程如下:

1. 在20120113_G113_硬卧long数组中随机获取符合要求的顺序的两个long数字,并将其从数组中删除;这个速度很快,纳秒级;

2. 根据long数字后32位,从数据库中锁票。如果全部锁定成功,设置票为预定状态,更新用户预定信息,锁票时间等。然后记录日志等其他相关操作。如果锁票失败,说明在纳秒级的时间内,票还是有冲突,购票失败,直接返回报错。锁票就是数据库行锁,sql中的 select for update nowait。

3. 页面提示错误,或者进入下一步交易流程,如网银支付等。

在整个过程中,我们看到,用户请求就算集中爆发,事务的冲突性也能降低到“随机获取的long数组值刚好一样 + 在cpu执行2000个for循环的可能百万分之一秒内刚好同时提交”。我觉得冲突概率应该很低很低。一趟车2000个车票,1:100比例也就20万人同时抢,20万人同1秒提交cpu也算的过来。而实际上,怎么可能一秒钟有20万人同时抢一趟车的票哪……

在整个过程中,大部分请求都被long数组消耗完后,直接检查long数组长度为0,提示无票拦截。进入数据库阶段的,也就是比实际的票数多一点点的有效订单而已。

回票:

中间站买票的,在预定成功后,车票自动分裂,分裂的票可以通过队列调度实时的回到long数组中,继续服务。

预定后不买的,可以通过预定时间的超时检查,后台做个线程,让票回归。

欢迎讨论。

微博:http://weibo.com/guzzframework



分享到:
评论
2 楼 qijunz 2013-02-25  
如查询2012年1月13号G113车次 济南->南京 的余票,就是遍历两个数组,检查位数为2和4的long数字有多少个,就直接获得了软卧和硬卧的剩余票数。对于现代计算机,这点遍历,时间是纳秒级的。

貌似查 济南->南京 的票不可能只查一列火车的票 而是多列同时
1 楼 zhaoxuhui97 2012-01-21  
12306的模型、功能应该都不复杂,这些内容相信铁科院等厂商已经研究的相当透彻了,也相当成熟了
我觉得12306的失败不在于他的模型设计、功能实现,而在于系统实施,合适的系统放到一个合适的需求、匹配的环境下才能成功。

相关推荐

    12306技术讨论 (附PPT下载)

    而提供的“12306技术讨论.pptx”文件,很可能是这次讨论的详细记录,可能涵盖了上述提到的各个知识点,包括技术原理、实施难点、解决方案等。 通过深入研究这些内容,我们可以对12306背后的复杂技术有更深入的理解...

    铁路12306互联网售票系统IPv6演进的方案研究.pdf

    IPv4地址空间的枯竭和网络智能化的发展趋势,要求铁路12306系统必须采取相应的技术演进方案,以适应未来的网络环境。 IPv6是下一代互联网协议,它解决了IPv4地址不足的问题,提供了更为丰富的IP地址资源,从而支持...

    12306互联网售票系统余票数据一致性保障技术方案研究.pdf

    "12306互联网售票系统余票数据一致性保障技术方案研究" 该论文研究的主要内容是12306互联网售票系统余票数据一致性保障技术方案。该方案的主要目的是为了提高旅客互联网购票体验,减少购票中出现的余票问题。研究...

    12306一直保持在线

    对于不熟悉这类技术的用户来说,这个文件至关重要,因为它能指导他们正确使用脚本来解决12306购票时遇到的问题。 在使用12306KeepLive.user.js时,用户需要注意的是,虽然这样的工具可以提高购票效率,但也可能存在...

    铁路12306线上智能客服系统方案研究.pdf

    铁路12306线上智能客服系统方案研究 知识点1:智能客服系统的必要性 随着铁路客票服务的发展,客服工作遇到了很多问题,如客服人员与服务需求严重失衡、热线一对一服务效率低、常见性问题占比大、人力耗费过多等。...

    12306服务器自动IP切换

    12306服务器自动IP切换是一个针对中国铁路客户服务中心(12306)的网络技术策略,它主要用于优化用户在高峰期购票时的网络访问效率。12306作为国内最大的在线火车票预订平台,面对节假日或春运等高峰期的巨大访问量...

    12306网页制作

    总的来说,“12306网页制作”是一项综合性的任务,它涵盖了网页设计原则、前端开发技术,尤其是JavaScript的应用,以及对用户体验的深刻理解。通过合理的技术选型和精心的设计,可以创建出一个高效、易用的在线铁路...

    12306铁路抢票软件

    对于有志于学习抢票软件开发的读者,可以从这个项目中了解到网络编程、前端交互、数据解析等多个方面的知识,同时也能体验到面对复杂问题时如何进行技术选型和解决方案设计。 综上所述,12306铁路抢票软件的开发...

    12306抢票助手

    综上所述,12306抢票助手是一种针对12306购票难问题的解决方案,涉及到浏览器插件开发、自动化技术、网络安全等多个IT领域的知识。在享受便利的同时,用户应关注其潜在的安全风险,并遵守相关规定。

    12306的数据库设计.pdf

    【12306数据库设计】的探讨主要围绕着铁路售票系统的挑战和解决方案展开,尤其关注高并发场景下的数据处理。在这个系统中,查询余票、购票、中转乘车规划等核心功能对数据库的设计提出了严峻的考验。 首先,查询余...

    12306订票助手.NET_2.5.0.812

    《12306订票助手.NET:高效抢票的智能解决方案》 12306订票助手.NET是一款专为解决中国铁路12306官网购票难问题而设计的独立工具。这款软件利用.NET框架开发,具备自动抢票、实时监控、智能识别验证码等功能,极大...

    rain12306-java swing实现12306客户端 无任何服务端依赖.zip

    《rain12306-java swing实现12306...这对于学习Java GUI编程以及理解客户端-服务器架构的替代方案有着极高的参考价值。通过深入研究这个项目,开发者可以提升在用户界面设计、事件处理、数据管理等多个方面的技能。

    12306订票工具(查票,订票,功能齐全,支持多种订票方案)

    在12306官方网站上订票时,用户需要手动选择座位类型和乘客信息,而在这款工具中,用户可以预先设定好购票方案,包括车次偏好、座位类型、乘车人信息等,一旦有符合要求的票源,工具将自动完成购票操作,极大地提高...

    C#12306自动订票源码V2.0版

    总的来说,这个C#12306自动订票源码V2.0版结合了C#编程、图像处理、自动识别、网络请求、数据库操作等多个IT领域的技术,为用户提供了一种智能化的12306购票解决方案。在实际使用中,开发者还需要考虑如何合法、安全...

    C#12306一键订票源码

    以上就是对C#12306一键订票源码的相关知识点的详细解析,对于想学习网络爬虫、自动化脚本以及C#窗体应用开发的开发者来说,这是一个很好的实践项目。通过研究和改进这个源码,不仅可以提升编程技能,还可以深入了解...

    最新火车票12306订票助手

    8. **行程规划**:对于需要中转的旅程,软件可能提供最佳中转方案建议,帮助用户节省时间和费用。 9. **用户体验优化**:界面简洁易用,操作流程直观,减少用户在12306官网购票时可能出现的困扰。 10. **隐私保护*...

    虚拟化技术在12306双活数据中心中的应用.pdf

    【虚拟化技术在12306双活数据中心中的应用】 12306是中国铁路客户服务中心的核心网站,负责全国铁路客货运输业务和公共信息查询。随着互联网技术的快速发展,12306面临着日益增长的用户需求和对高可用性的严格要求...

    编程乐趣:C#实现查询12306票价信息

    总之,通过C#实现12306票价查询涉及到网络请求、HTML解析、模拟登录等多个技术点,需要对Web开发有一定的理解。在项目`TestQueryTrainTicketPrice`中,这些功能可能已经实现,你可以通过查看源代码来学习和理解具体...

    12306Bypass_1.9.10

    总的来说,12306Bypass_1.9.10是针对12306购票难题的一种技术解决方案,它体现了技术在生活中的应用价值。然而,作为用户,我们也应意识到技术应用的伦理和法律边界,合理、负责任地使用这类工具,共同维护一个公正...

Global site tag (gtag.js) - Google Analytics