西西河

主题:【原创】无责任推测12306网站遇到的麻烦 -- 代码ABC

共:💬135 🌺246 新:
分页树展主题 · 全看
/ 9
下页 末页
  • 家园 【原创】无责任推测12306网站遇到的麻烦

    首先声明,这是技术贴,也许有点阴阳怪气,但不洗地,咱纯粹看戏。

    其次本人无任何内幕信息,也没有参与铁路部门任何项目,所以许多假设仅仅是假设。如有雷同那是运气,如果与事实不符也很正常。

    我的假设主要基于两个数字:一个是新闻里说的铁路春运期间,每天平均运送旅客7000万人次,另一个是每列客车可以载1000人上路。另一个假定是12306网站和铁路的内部票务系统无直接的数据连接——这个假定我认为是靠谱的,因为窗口售票并不受网站瘫痪影响,证明铁路内部系统运作正常。因此进一步推断:铁路部门每天给会将一张可售票总表交给网站,里面大致应包含时间、车次、各车次可受票的种类和数量。12306网站则定时提供一张汇总表报告售票情况。

    那么我们来分析一下设计这个网上售票系统所需要考虑的问题。

    相信通过这几天的表现我们知道整个系统的核心在于用户的使用压力上,其实网站的功能并不复杂,核心的功能(按使用频度顺序)就是票务查询、订票、用户身份验证和注册,另外就是一些杂七杂八的辅助功能,如:订单管理、个人资料修改等等。数据库(假设使用数据库解决方案)内的数据主要就是用户数据、车票数据和订单数据。

    我们先看最简单的用户数据部分,这部分相关的操作是注册、登录,当然在订票的时候也会用到,但一方面在订票数据里这应该只是一个外键,另一方面可以暂时缓存在用户的交易会话中,所以实际会操作到这个数据的就是上述两个动作。注册是一次性的,登录则不是,因此查询动作会多一些。但无论如何这个数据表(假设设计成一张表)的查询非常简单,优化也很方便。所以这个表虽然很大(目前数据超过1000万),但乱子不会出现在这个地方。其实12305的登录动作是很快的,那个人数太多只是一个临时措施免得太多人同时进行交易而已,留意一下只要能登录进去那个登录页面反应其实不慢就是这个道理。

    我们再看订单数据,这个数据也会很大,因为需要存放每张票的详细信息,如果每天有四分之一的票是通过网络出售的那么这个数据是每天增加近2000万条。不过这个数据表(假设还是一张表)主要的动作就是插入和修改,几乎不会查询。所以优化也不困难。这里设计的麻烦在在线支付和相关的车票数据锁定的问题上。当我们选好票进入支付环节的时候,系统必须首先将选好的票锁定起来,也就是余票查询将会扣减相应的票数。这个操作的复杂性比登录要高就在于这点,需要同时修改两个地方:车票数据和订单数据,而且必须是同时的。在数据库设计上这叫要求事务的完整性。通常这种操作需要通过锁定一些数据记录来完成,也就是当系统修改车票数据和生成订单期间,车票数据和订单相关的车次查询将被暂时中止。这样订票就影响了查询性能。反过来也一样,查询的时候也不允许生成相应车次的订单。其实这有点扯,系统真正要防止的是当只有一张票的时候,如果有多个人同时订票那么只能有一个人成功,虽然他们之前都查到有一张余票。所以实际上需要保证的是一个时间只有一个人可以修改车票信息。因此,为提高性能我们可以放宽对查询准确性的要求,即查询操作不锁定车票信息,不理会当前有多少人在订票。反正大家心里有准备最后几张票都是抢的。当然锁定范围肯定不是整个数据表,而是订单相关的车次记录。也许12306的第一个瓶颈问题先发生在这里吧。因为如果查询和订票会相互影响的话,那么怎么优化都有问题。我猜他们后来搞出一个30分钟更新的数据就是为了提供一个单独的车票数据表供查询用,这样大致上隔离的订票的查询之间的冲突。也许他们忘记数据库事务控制中锁的作用吧。我这样大而化之的分析肯定有很多错误,不过这是一个所有DBA和程序员都应该知道的基本常识。接下来的车票数据可能会更复杂,也许是当前即使使用用一个单独的数据库来进行余票查询也非常慢的原因吧。

    车票数据我的估计是这样的,每天有7万个车次(7000万/1000)。靠谱吗?我估计数量级大概是靠谱的。谁能给更准确的数字?请不吝赐教,谢谢。车次的问题在于除非是直达车,否则一个车次可以分开好几段来售票。那么7万车次就可能不只7万条记录,这里还会牵涉到几个让一般程序员感到棘手的算法问题。算法?拜托都还给老师了吧。实际上怎么存放车票信息将牵涉到具体如何实现余票查询的算法。举个例子:有一趟车从广州开往北京,经停南昌、株洲(铁路知识一片空白,地名乱填的,别拍砖哈)有10张卧铺票。甲买了一张广州到株洲的,这时株洲到北京还剩10张,广州到北京就剩下9张了。实际还需要扩展一下,如果有人查南昌到株洲呢?还是9张,广州到株洲呢——9张。经停站越多,起始站和终点站的组合就越多,这个算法复杂性就在这里。设计这种信息的存放就是一个挑战。如果列车的售票模式是允许这样的话,我想我知道他们的麻烦在哪了。

    首先最笨的方法是,每个车次只存一条数据记录,然后关联另一张节点表(存放经停站点用)。这样查询余票的时候需要联合这两张表(还可能有计算)并汇总已有订票记录表。这种存放方式的特点在于数据冗余少。但是查询开销极大,因为需要访问一个庞大的订票数据表(每天2000万的增长)。如果哪个坚持数据库范式的DBA这么干,那么一定就悲剧鸟。

    不过我们可以从上面开始优化,其中可以将订票数据表生成一张汇总表。(毕竟我们只需要知道已经出售的票数,而不需要知道哪张票是谁买的)只记录车次、起始站、终点站的售票张数。这样可以把每天2000万的数据缩减为每天差不多70万的数据,具体估算如下:假设一次列车平均5个站,那么起止组合就平均有10左右(不严格)车次。那么每天汇总就是7万x10,约70万条数据。几天下来就是几百万。不过由于需要联合多个表查询,其处理集合的数量级还是上千万甚至上亿。这样对于高负荷网站来说还是有点受不了。而且汇总数据和订票数据相关,不能实时生成。也许这能解释为什么余票数据改成30分钟一次。

    再进一步,其实我们可以把车次数据直接拆开了存放,也就是每个车次直接存放为各种起止点的组合,而且直接把余票数据放进来。这样查询的时候一张表就搞定了。每天增加70万数据,12天的票也在1000万的量级。这样性能好点的服务器应该就可以解决问题了。麻烦只在于这时候订票操作需要修改多个数据。但是订票操作应该远远小于查询操作。整体来看系统性能还是可以提升不少的。

    实际上,这个问题有很多解决方法,由于手头没有详细的车次数据、铁路局的节点数据、用户查询习惯等支持。所以没有什么建议,但有一个直觉就是纯数据库解决方法可能不是最优解。也许转换成有向图直接在内存中计算会更快。而且还能增加转车计算的功能。没有数据再掰下去就太YY了。鞠躬,下台。

    通宝推:雪君,文字君子,铁手,muilho,
    • 家园 从实际订票操作感受猜测系统实现

      春运期间,我成功为家人订票一张,自己订票6次成功,改签两次成功,退票两次成功。

      我的发现是,余票数据不准确,有些车次查询有余票,但反复订票不成,系统提示“忙!”,换车次则一次成功。

      猜测余票数据是定期从另一个系统导入,而订票则是实时交易的。

    • 家园 今天遇到了相关的技术人员,搞明白了,网上99%的说法

      都没说到点子上。有些细节恕不能详说。基本上是这样的。

      网上订票系统只是一个壳子,跑在jboss上面。后面有一个legacy system,这个已经运行了近20年的老古董了,也就是在窗口售票中使用的系统。但致命的是,这个legacy system完全无法scale out,这里涉及一些细节,但每一个初级的架构师听到这个细节都会明白,确实这样是无法scale out的。

      网上订票系统,原在刘志军时代是设计用来卖高铁票的,那么原设计倒是无问题的。但新部长非要卖普票,各供应商包括铁科院自己都觉得很崩溃。因为接到要卖普票的要求时,已经不到4个月的时间了,这个时候再改技术架构已经没可能了。

      总之网上说的一切scale out的方案都完全无可能,原因在于其真正的transaction部分都在那个legacy system中,完全无法剥离。(理论上剥离当然可以,但时间不够,且如果春运时做这个工作,相当于连窗口售票都要崩溃,那就成了政治事件了)。

      这个系统运行起来后,如果假设总体连接能力为N的话,大体只给互联网售票留了很小一部分连接能力。这样至少保证了窗口售票还能正常进行。

      春运期间这事最终还是靠scale up的方式解决了,HP卖给铁道部一台128个CPU的服务器,算是这次最大的赢家了。

      这个事件里还有个有意思的地方,看这贴的人应该都知道有一篇称赞淘宝架构如何NB的文章。事实是,淘宝团队1月4日就到铁科院去帮助调优了,但最终也只有选择了scale up的方案。为何后来淘宝不再唧唧歪歪了原因也在这里,从上海杭州抽调了20多个骨干精英去干这事,也没有找到更好的方法。当然了,对马云来说也是重大收获,马总对团队的指示是不计成本要帮铁道部解决这事儿,换来的就是要求铁道部支持支付宝独揽支付业务。TB算是仅次于HP的大赢家吧。

      • 家园 HP 128个cpu

        128个安腾cpu的 superdome吧。

      • 家园 那马云的团队没干成这事,铁道部还支不支持他呢?
      • 家园 可信度不高

        难以相信国内会有运行近20年的legacy system还在跑,1990年代中期是什么软硬件环境,能跑到现在真是个奇迹了。中国这种大单位的一个特色就是新领导上台总要大干一场,这么多年铁道部换了多少部长了,还让后台的近20年的legacy system还在跑对铁道部简直是一种侮辱。

        • 家园 国内的legacy系统一定没有国外多(从数量到比例都是)

          legacy是指其架构,人家软件硬件也定期升级的。legacy也是一个模糊的概念。IBM主机就是所谓的legacy,大家不是天天在用?(只要你的钱是在几大行,或多少国外的银行,你就legacying)

          铁道部的legacy是基于Sybase(现在那个新系统还用?)的,估计所谓无法scale out,是其数据库产品本身设计,没有办法共享锁信息。所以只能scaleup,也就是提高CPU,内存,I/O,让当交易的时间缩短,而不是提高交易和数据访问的并发度。

        • 家园 做过企业软件的人知道

          20年以上的系统多了去了。不是不想改,是很难改。

        • 家园 这个系统就是窗口售票系统,出问题的话全国的火车票都卖

          不出去了。您NB,您当领导就敢冒这个政治风险,一年换一次是吧。

          • 家园 简单分析一下

            90年代中期铁路的全国性联网能否做到还是个未知数,那时候的软件设计思想更是很简单,基于这个我认为近20年前的legacy system不可能保留到现在。软件行业20年早已天翻地覆。就拿银行来说,业务肯定要比铁路售票复杂,也是经历了一个储蓄所一台单机版、全市范围的联网通存通兑、全省范围的联网到后来的全国性联网,这个变化是沧海桑田式的。铁道部竟然近20年核心系统不动,这还是中国的铁道部么?

            我不是说你说谎,我是认为这个20年大概是你听错了,IT行业说20年前跟说200年前没区别。

            • 家园 更具体的说

              这个系统开始是pb+sybase,现在还是,只是版本升级到了5.2.

              知道现在,大多数网点还是用的电话拨号的方式连入网的.你说这么多年架构算不算有大变化?实际上中间本来铁科院想有一次大的改变,结果由于种种原因实际上失败了.

              • 家园 我的推测中有这个信息。确切的说是2套系统

                TBS 是老的,基于Sybase。

                TRS是新的,基于oracle ,但是好像有点失败。

                两台系统是独立的,卖的车次不一样,TRS好像是买部分高铁。

              • 家园 我知道铁路售票系统前端用的是pb

                10多年前我用pb的时候就知道,而且我在窗口买票的时候看他们的界面也能看出来是pb做的。

                10多年前pb只能直接连数据库,而现在不用3层结构感觉不可能,网上售票,还有全国各地众多的网店、代售点,不可能直接拨号进去连数据库吧?

分页树展主题 · 全看
/ 9
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河