V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
epis2048
V2EX  ›  程序员

12306 居然又被拿出来讨论了,我想发表一些自己的见解

  •  6
     
  •   epis2048 · 2023-01-05 21:13:47 +08:00 · 5003 次点击
    这是一个创建于 693 天前的主题,其中的信息可能已经有所发展或是发生改变。

    首先说一下,我才疏学浅,技术能力并不过关,技术方面我能讨论的不多。

    不过这些年我对铁路的了解应该在这个论坛里比大部分人多,我想说一说我了解的铁路方面的事,以及 12306 的一些细节。

    1. 12306 只是一个前端网站,他的作用是将售票核心网的接口暴露出来,供除了车站售票处之外的其他旅客调用。

    2. 铁路现在是各个路局各自为政,每趟旅客列车都是有所属路局的,售票核心网的服务器其实是在各个路局内。举个例子:郑州水灾的时候郑州局所辖列车票务业务短暂中断过一段时间,因为郑州局的机房在-1 层,被水淹了。而快速恢复则是因为铁科院内部对各个路局的设备都有一套备份,所以切过去就好了。

    3. 目前铁路单纯售票业务计算压力并不大,因为一趟车他就那么几千的座位,而每趟车之间在售票业务上没有什么关联,可以加服务器简单解决。而且售票核心网事实上已经很多年没有大改过了,这些年实名制、电子客票、积分兑换,都是修修补补级别的。

    4. 12306 最大的压力在查询余票,因为这个功能直面旅客,相当于被 DDOS 了。这个确实是靠多级缓存+云服务等实现的,至于技术是阿里还是铁科院提供,我不能确定。想必各位都有这样的经历:在买票时,明明显示有票提交后却报无票 or 自己显示没票,别人就显示有票。这个恰好能说明在这种量级下,保持缓存一致性是很困难的。(车站售票窗口以及车站自动售票机应该是可以直连售票核心网的,如果是想买临近要出发的列车,可以尝试在人不多的售票窗口让他给你刷一刷,或者在自动售票机上刷,比自己在手机上刷有用的多)

    5. 铁路在售票不联网之前,每趟车会为其经过的车站提前分配票额 /位置的,这个机制至今仍在沿用。这种机制就造成了所谓的区间限售(一趟北京南到上海虹桥的车,你搜全程有票,搜天津南到上海虹桥就没票,实际上就是预先把大部分票额分配给了北京南)以及很多人感受附近的人似乎一起下车等。这种区间限售,客观上减缓了售票系统计算的压力,也提高了铁路的利润率(还是比如北京南到上海虹桥的车,如果天津南到上海虹桥被买走了,那这个座位北京南到天津南就很难被卖出去),当然客观上会造成对短途旅客以及出发 /目的为小站的旅客的不便。( PS. 以前区间限售几乎都是开车前 24 小时解除,不过现在似乎这个时间变的随机了,就像退票随机延迟返回票池一样)

    6. 售票最大的压力还是来自于刚起售的时候,等到解除限售之后,虽然牵一发动全身的情况会很严重,但是这个请求量并不大。我个人推测,解除限售时间的动态变动,其实应该和售票系统压力与票卖的好不好都有一些关系。不过这两个原因之间本身就是关联的。

    7. 铁路关于减缓售票压力所做的努力,其实除了技术之外还有很多行政方面的手段。比如之前提到的区间限售就是一种,还有大家可见的不同站起售时间不同、候补购票以及购票等候队列等。12306 的成功是多管齐下的结果。

    8. 现在 12306 我个人觉得软件还算好用,当然前提是不要打开 F12 看 Ajax 请求,不然可能发现在同一个请求下,变量能有好几种命名方式及传递方式(这段话和主题无关,纯粹是看见之后感到有些惊奇)

    也许这个帖子可能会让一些人觉得我认为 12306 没什么技术难度。但是我想说,我无法判断他到底有多难,我只知道他既不像有些人说的那么简单,也不像有些人说的那么难。(好像是句废话)

    其实我发这个帖子,主要是觉得大家关于 12306 技术的讨论好像和我了解到的不太一样。希望大家能平和讨论,无论对方持什么观点,尽量不要人身攻击。

    第 1 条附言  ·  2023-01-05 23:08:38 +08:00
    其实我个人认为,应该区分开 12306 和售票核心网,这是两个不同的系统。

    大部分人说关于卖票时算座的算法等,这个是售票核心网实现的,而这个售票核心网并发量并不高。

    而 12306 则是常规互联网所面临的问题,涉及支付、实名制等等。售票核心网可以算是 12306 的一个后台支撑系统,关于究竟有多少请求进了这个系统,我个人认为是很低的。

    而且,对于售票核心网,既然不同车次能通过所属路局进行拆分,那我认为这个系统横向扩展,即车次数量增加之后以不同车次进行拆分并不难,因为他本身的拆分逻辑就是一种天然带随机性质的行政划分。
    31 条回复    2023-01-08 07:18:42 +08:00
    vitoliu
        1
    vitoliu  
       2023-01-05 21:23:17 +08:00 via iPhone   ❤️ 2
    最难的点就是架构,你的网络和后端服务该怎么设计,业务怎么切片。流量洪峰下你能不能保证你服务的 HA ,一长串的链路走完,到最后的数据库缓存更新这,流量肯定是不高了。
    watzds
        2
    watzds  
       2023-01-05 21:35:25 +08:00
    写得不错👍,没有传说中的那么难,但是任何一个系统要做完善,肯定也不容易。
    epis2048
        3
    epis2048  
    OP
       2023-01-05 22:00:21 +08:00
    @vitoliu 我同意架构方面可能比较困难,不过之前看很多人讨论,都过分局限在售票这个操作上了。这也是我写这个帖子的目的,希望大家可以发散一下思维,研究一下 12306 在其他方面的努力。我觉得,包括通过行政手段来解决问题,难度并不会低于技术手段,这都是可以关注的点。
    epis2048
        4
    epis2048  
    OP
       2023-01-05 22:10:33 +08:00   ❤️ 1
    铁路其实是一个非常复杂的系统,其从早期的原始阶段,到现在逐步迈向自动化,是付出了大量非技术方面的工作的。从没有任何设备的帮助,到现在基本实现机械化自动化:其规章是如何进步的;故障导向原则是如何落实的;大量复杂而又一环扣一环的规章是如何被技术手段简化的;同样,技术手段是如何引起规章变化的。这都是很有趣的内容。

    比如一个和客运有关的东西:通票,他的作用是在没有直达车的时候帮助旅客完成中转。在最新版本的客规中,通票被彻底删除了,成为了历史。在客规中取代通票的,是 12306 的中转换乘功能以及 12306 中关于接续换乘列车改签、退票的逻辑判定。(当然,在高铁大范围开行之后,通票就几乎消失了,这个原因很复杂,我也说不太好,我觉得可能还是和联网售票有关。但是从旅客的角度,通票的功能被新技术取代了,这就是技术进步带来规章的简化)
    wudidada
        5
    wudidada  
       2023-01-05 22:19:09 +08:00   ❤️ 1
    之前选修过并发数据结构和多核编程,大作业就是设计一个火车售票系统。

    记得判断并发计算是否正确的方法就是看并发操作是否是可线性化的,像你说的一个用户显示有票,一个用户显示无票,可以看作写入和查询的操作重叠了,在写入操作没完成之前,查到有票和无票都是可以的。A 查到有票,B 查到无票,那么可以线性化为 A 查询->买票->B 查询,别的情况也是这样,总能找到一个正确的线性化的序列。

    作业的题目十分简单,仅仅是十几辆火车,十几个车站,一辆车十几个车厢,大多数人在服务器上 64 线程运行的吞吐量也就一两万。这还是尽可能细粒度地操作数据结构才达到的,后面那怕优化一点点都很艰难。

    真实的环境下,有这么多车次、车站、座位,要维护这么庞大的并发数据结构的正确性的同时还要提供强大的并发性能,确实是很难的事,应该不是简单地增加服务器数量就能实现的。
    Damn
        6
    Damn  
       2023-01-05 22:27:48 +08:00
    @epis2048 啊,通票已经消失了啊!我还说找个时间弄张搞笑的通票纪念一下呢,这三年一直没什么机会去。。
    zpf124
        7
    zpf124  
       2023-01-05 22:29:49 +08:00
    1 、单纯以前后端交互来说,12306 一直稀烂,虽然如今已经好多了,但还是不咋样。

    2 、不清楚所以就不瞎说了。

    3 、车票联动售卖部分是确实存在的,而且应该非常繁杂,A 到 C 的票卖一张、A 、A2 、A3 、B 、B2 、C 之间的可售票都需要减去,但这部分应该是跟着铁路售票窗口电子化建设一起搞起来的内部系统,12306 可能不会涉及他们的售票库存逻辑,只是支付-确认支付-调铁路内部出票接口。

    4 、这个属于既简单又麻烦的地方,简单是神仙来了处理 DDOS 也只能加机器,钱就可以解决,难则是难在峰谷差距太大,自建花费完全不值得,如今用阿里云玩弹性扩缩容确实是个比较好的方案。

    5 、铁路确实有区间预留车厢,但只预留大站,并且大站也有非预留部分,比如 3 中 买 A 到 C 可能会买到 2 个预留车厢或 5 个混卖车厢的票,其他车厢则是 A 到终点的或到临近终点大站的预留车厢。
    所以在非预留车厢的车票计算一直比较复杂,并且到了快发车时所有的 A 站预留车厢都会开放售卖,后面的 A2 、A3 这时可以买的 A 站的预留车厢票。 这部分绝对很复杂,不够和 3 提到的一样,这部分售票核心逻辑是铁路电子化建设的部分,搭建 12306 的时候应该已经是建成的了。

    6 、和 4 一样,还是 DDOS 的问题,这部分目前的解决方式是不同始发站开售时间分开,这部分 12306 的压力除了查询应该只有购票失败可能涉及的退款了。

    7 、候补这个可以归于 12306 的功能设计,还有购票信息实名制校验、错开各始发站车票起售时间、网络退票随机延时后放出这些都是 12306 层面做出的尝试,而行政方面我没有想出来到底有哪些有效措施了(唯一想到的是警察打击高技术黄牛抢票窝点), 区间预留车厢是实际需求而不是解决手段他窗口售票时代就有了。

    总结:
    如果你把属于 12306 的核心功能,但现实情况是不涉及相关算法开发的部分——票务数据管理系统排除在需求列表中,则整个系统难度不算太高,需求重点主要是特定时间的高并发、实名身份校验、支付逻辑、支付确认逻辑、退款逻辑等互联网常规功能,难度与聚合多个平台的返利网站只有并发的差距。

    如果你的开发包含了铁路系统最核心的票务管理功能,则开发难度远超大多数软件,因为处理功能复杂设计开发难度大之外,还会涉及许许多多的微小但必须修复的细节,需要开发者在未来的多年内一直重复,试用-反馈-修复,试用-的维护流程。
    christin
        8
    christin  
       2023-01-05 22:30:34 +08:00 via iPhone
    @epis2048 通票我发表下自己浅显的观点,抛砖引玉。
    一张通票比一站火车票占用的计算量会大一点,因为一张通票要用在两辆火车上使用,所以计算量是一张普通火车票的至少两倍。而且更容易出现你说的买了某一区段导致全程其他地方票卖不出去而空座的情况。
    zpf124
        9
    zpf124  
       2023-01-05 22:35:31 +08:00
    7# 校对错误:

    5 、“不够和 3” ——> “不过和 3”

    总结: '因为处理功能复杂" ——> “因为除了功能复杂、”
    eason1874
        10
    eason1874  
       2023-01-05 22:38:14 +08:00
    这么大规模的系统,做起来当然不容易,只是用多了也会发现没有前几年吹的那么难(以前网上说车票库存是实时计算的,以此论证难度大,真是这样的话,确实难度大,但并不是)

    其实 12306 就是一个大号淘宝,全程票、区间票都是提前定好数量来放票的
    christin
        11
    christin  
       2023-01-05 22:39:20 +08:00 via iPhone
    @christin 而且我对通票的换乘成功率不抱太高的期望,除非能在火车站建立换乘快速通道,否则有可能出现换乘没赶上的情况。一种比较理想的换乘方式是乘客在中转站下车后可以尽快坐上下一辆车走人,但是不能保证下一辆车的时间,如果都安放在大站换乘会导致大站会出现一些临时的超额人员,这些人只是在等换乘,但是却要占用固定的位置;如果安排在小站,小站不能保证短时间内有下一辆车,乘客可能要等好久。
    Damn
        12
    Damn  
       2023-01-05 22:50:45 +08:00
    @christin 通票的问题是过于古老,很多没上一定年纪 /级别的人都没有听过这东西。
    通票需要中转签证,如果不是老牌车站,很有可能闹得整个车站鸡飞狗跳都签不下来,或者换乘时间太短整个车站鸡飞狗跳眼看着快签下来了,车开走了。
    epis2048
        13
    epis2048  
    OP
       2023-01-05 22:52:37 +08:00
    @christin 呃我觉得您理解的可能不太对,通票是一个历史遗留问题,12306 其实压根就没有过这个功能
    singerll
        14
    singerll  
       2023-01-05 22:53:13 +08:00 via Android
    我的看法是,这个系统远远不止大家看到的这么简单。大家都在讨论怎么卖车票,但我觉得 12306 除了卖车票,肯定也会跟铁路调度、财务系统等一大堆系统对接。

    这么多东西,架构上谁都能扯几句,但能给出完整方案的并没有几个。

    就跟造原子弹一样,核聚变公式高中生都能写几行,原理也能扯几句,但别说高中生,博士生也没几个能真正造出来原子弹的。
    Damn
        15
    Damn  
       2023-01-05 22:53:51 +08:00
    @christin 真是可惜了,通票在多年前最近那次改版就只显示首程信息。东方红-太阳升这种神奇车票再也没有了。
    还有随着经济发展各种小站的消失,比如六个鸡什么的。。
    epis2048
        16
    epis2048  
    OP
       2023-01-05 22:58:05 +08:00
    @zpf124 是的 售票系统的核心逻辑一定是很复杂的,这个逻辑问题也来源于复杂的规则,是我国铁路这些年逐步积攒下来的,甚至很多规定都可以说是屎山。不过我想说的是,其实这个售票逻辑跟 12306 没什么关系...12306 主要是实现了互联网的那些功能。核心算法逻辑可以说是售票核心网的问题,而这个系统其实并发量并不高,甚至还是 24h 运行的,近 10 年也没有太大的更改。
    epis2048
        17
    epis2048  
    OP
       2023-01-05 22:59:23 +08:00
    @christin 通票和中转换乘不是一类东西,通票你到了换乘站要重新签票重新去售票处选车次的。这个本身就不被当今社会所适应,所以自然就消亡了。
    epis2048
        18
    epis2048  
    OP
       2023-01-05 23:03:46 +08:00
    @zpf124 啊对了...还有个问题,我指的前端不是网页那个前端,是整个售票核心网的前端,即:负责调用内部接口出票。

    另外行政方面我指的不是 zf 采取的措施,而且铁路通过管理的手段来解决的问题。我认为,区间限售、起售时间这些都应该算作管理手段。至于技术手段,则是单纯的加机器与优化算法。
    christin
        19
    christin  
       2023-01-05 23:12:18 +08:00 via iPhone
    @epis2048 感谢指正。
    epis2048
        20
    epis2048  
    OP
       2023-01-05 23:16:46 +08:00
    @singerll 所有大型系统都具备天生复杂性。隔壁那个问题,其实是个很大的问题,因为 12306 中子系统也很多很杂,甚至很多和 12306 的主要业务没什么关系,而且业务逻辑也是一坨屎山。

    架构方面可能大部分人确实不配指点访问量这么大的一个系统。我只能从我知道的部分,提供一些信息,让大家猜测一下这个系统到底是如何运行的,他是如何处理数据的。至于他到底有多复杂,可能只有铁科院电子所的人才能说清楚了。
    wolfie
        21
    wolfie  
       2023-01-05 23:19:33 +08:00
    复杂,但并不觉得很难。
    好多人进入一个误区,不恰当的例子 不清楚国足厉害不厉害,反正吹国足就对了。
    terrytw
        22
    terrytw  
       2023-01-06 09:18:54 +08:00
    很多人其实都有一个误解,把这个事情当成一个纯技术的问题在讨论
    或者说没有明白需求方是谁

    你看那个帖子里有前员工的答复

    1. 全局性事务
    现阶段最难的是全局性事务, 因为保密原因, 不能说太多, 一句话概述就是整个系统存在事务问题导致的性能低下
    2. 流量压力
    众所周知
    3. 前置检查
    你买一张票的前置检查多到你无法想象, 目前的做法是线性检查, 提过并行检查的意见, 被否了
    属性 /规则 /()保密)上的检查
    4. 车票区段售卖
    其实车票不是 12306 卖的, 实际卖票的是 18 个铁路局, 12306 只是一个售卖平台.
    12306 只是拿到票然后根据用户提交的席位来分配这些票.

    其中除了第 2 条是用户导致的
    134 其实绝大多数时候都是各级 gov 的行政要求导致的复杂性

    12306 从来都不是一个以解决乘客需求为第一优先的平台,乘客的体验当然不好
    terrytw
        23
    terrytw  
       2023-01-06 09:21:47 +08:00
    总有人讨论 12306 开发的时候,如何计算余票
    你有没有想过,计算余票的逻辑,根本不是公平公正的,不是以让有需求的乘客买到票为目的的
    计算余票的逻辑,首先要考虑领导的意见(看到前员工说的保密了嘛?),各铁路局的利益

    复杂的点在这里,你头上有一堆爹,但是乘客不属于其中之一
    yaphets666
        24
    yaphets666  
       2023-01-06 09:54:21 +08:00
    和我在体验上反推的推测是一样的,售票算法并不智能。
    napsterwu
        25
    napsterwu  
       2023-01-06 09:58:11 +08:00 via iPhone
    这几年抢票其实一直有一个疑惑,还请有知道的大佬不吝赐教。
    问:A->B 站的票,真正起售时间是什么呢?是 A 站起售时间吗?还是列车始发站起售时间?还是列车途径所有站点中,最晚的起售时间?
    比如深圳北( 9 点起售)往汕头,大多数列车是广州南( 10 点)始发,途径惠州( 8 点 30 ),潮汕( 14 点)。这样的列车是不是 14 点之后才会开始放票?
    wttx
        26
    wttx  
       2023-01-06 10:03:01 +08:00 via Android
    @terrytw 毕竟对于 12306 ,只要运能满足不了,就总有人买不到票,需要抢票时,并不缺乘客,🤣
    AyaseEri
        27
    AyaseEri  
       2023-01-06 15:31:06 +08:00
    @napsterwu 我记得是按出发车站,与车次没关系。
    xiaotianhu
        28
    xiaotianhu  
       2023-01-06 16:41:39 +08:00
    说起来大家对这玩意这么有兴趣,真希望有哪个参与了的大神写一下这玩意的技术优化原理啊。hhh
    epis2048
        29
    epis2048  
    OP
       2023-01-06 20:35:29 +08:00
    @xiaotianhu 我觉得 这个压根不是一个技术问题,所以才导致网络上争论很多,谁也无法说服谁
    epis2048
        30
    epis2048  
    OP
       2023-01-06 20:38:02 +08:00
    @napsterwu A->B 的车票,只取决于 A 站的起售时间,与车次、目的地、经由等全无关系。至于起售时间,12306 可以查询

    事实上,在刚开始放票的时候,车票是严格遵守配额的,所以每个车站起售时间不同,也不会影响抢票的公平性。
    Nnq
        31
    Nnq  
       2023-01-08 07:18:42 +08:00
    架构上以及算法上都比较难的一个实例,一部分要保证 HA 同时还要有运筹学来保证最优解, 目的地是多个,相比航空两点或者三点,这个难度更大。 航空公司都经常有超售的情况
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1668 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:54 · PVG 00:54 · LAX 08:54 · JFK 11:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.