当前位置: 主页 > 数据库

12306用什么数据库-12306数据流程图

发布时间:2023-02-09 22:21   浏览次数:次   作者:佚名

标签

PostgreSQL, 12306, 春节, 一票难求, 门禁广告, 数组, 范围类型, 抢购, 排他约束, 行情分析, 广告查询, 火车票

背景

春节马上就要到了,又是火车票销售的旺季。 抢票的问题还存在吗?

还记得10年前春节前买火车票,要在出票前一天搬个小板凳排队。 热门线路,排队一晚也未必能买到票。

随着互联网的发展,几年前建立了12306网上购票系统,可以在电脑上购票,但不要以为在电脑上就可以买票。

记得12306刚上线的时候,12306网站经常打不开,无法支付。

为什么?

原因很简单。 春节期间,在线购票人数可能达到数亿,而且售票日期为同日同时,这意味着12306将同时接待数亿用户的访问。

处理能力和实际访问要求更差,结果是网站打不开,系统不稳定。

12306的数据库设计

后来12306想出了开通不同线路和时间段的方法,试图错开不同线路用户访问12306网站的时间,但这种方式一开始效果并不明显,也不是所有用户都知道吧(像你今天通知暂时不上班,但还是有用户会来单位),所以大部分用户还是专心一点访问12306网站。

随着硬件的发展和技术的演进,12306系统越来越成熟,稳定性和响应速度也越来越好。

据说很多商家也开通了云抢票服务,本质上就是让你不打12306系统,提前把需求收集起来。 当票被释放时,这些系统将排队并合并购买。 这个方法可以减少12306访问并发。

抢火车票是一个很有意思的话题,对IT人员的智商和IT系统的健壮性,尤其是数据库的功能和性能都是一个挑战。

接下来,我们来看看难点和解决方法。

1.铁路售票系统-西游记开始

铁路售票系统最基本的功能包括

查询余票、余票统计、购票、车次变化、退票、改签、中转乘车规划 等。     

每个需求都有自己的特点,比如

1.查询剩余门票。 用户在购票前,通常会在目的地查看剩余的车票。 这是一个高度并发的操作。 同时需要统计剩余票数,需要强大的CPU支持实时查询。

2.买票。 购票不同于查询。 买票会改变库存,所以是对数据库的更新操作。

而且,买票可能会发生冲突。 比如很多人要买同一趟车的车票,就会发生冲突。 谁会卖给他们?

需要考虑锁冲突,尽量让不同的人并行购票,或者合并多个购票请求,减少数据库更新操作。

3、对于中转乘车,当用户需要购买的始发站和目的站都没有车票时,需要计算中转乘车计划。

比如北京到上海没有直达车,要不要换车? 什么时候转移,转移到哪里就成了问题。 简单来说,就是买票的人自己考虑。

如果再高级一点,可以让12306给你推荐路线,这涉及到数据库的路径规划功能。

我们来一一分析这些需求的特点。

1 查看剩余门票

1.普通剩余票查询需求

如果你想买从北京到上海的火车票,你通常会查看哪些车次还有余票。

查询的过滤条件可能有很多,比如

1.1. 上车站、下车站、中转站

1.2. 列车类型(高铁、高铁、直达、特快、普通客运……)

1.3. 出发日期和时段

1.4. 到货日期、期间

1.5. 座位类型(硬座、硬卧、...站票)

1.6. 过滤掉没有剩余车票的火车

在展示给用户的时候,还需要考虑如何排序(是按出发时间排列,还是按票价排列,还是按剩余票数排列?),如何分页。

12306的数据库设计

12306用什么数据库_大数据 思考 12306_12306数据流程图

眼见为实

查询余票通常不是实时的,也不一定准确,可能是后台异步统计的结果。

即便是实时统计的结果,在高并发抢票期,你看到的信息也可能很快对你失效。

比如你看到某趟车还有100张票,很可能等你付款的时候已经卖完了。

所以在高峰期,余票信息的参考价值不大,大家不要混淆。

2、查询余票还有一个更高级的需求是路径规划和自动适配(根据用户输入的中转站)

这个功能以前可能没有,但总有一天会曝光,尤其是在票很紧的情况下。

比如从北京到上海,就没有直达车了12306用什么数据库,系统可以帮你查询一次换乘,二次换乘,N次换乘。 (当然,转的越多越复杂)。

从中转的角度,实际上已经涉及到路径规划的技术。

如何转让就是时间最短,价格最低,转让次数最少等等。 (还涉及到换乘的输入要求(比如用户要求在一线城市换乘,或者必须换乘高铁))。

关于路径规划,可以参考PostgreSQL pgrouting,支持多种路径规划算法,支持算法的自定义扩展。

简直是居家出行杀人的必备良药。

《聊聊双十一背后的技术——物流、动态路径规划》

主人小心,有怪物。 . .

1. 大多数用户都有选择综合症。 一般来说,用户在选择合适日期的合适火车票之前可能会查询很多次。

查询量比较大,尤其是春节期间。

2.为了显示剩余票数,需要进行统计,会消耗较多的CPU和IO资源。

3.路线规划,帮助用户选择最佳的换乘路线,是对数据库功能的考验,大部分数据库都没有这个功能。

2 剩余投票统计

对于售票系统来说,查询剩余票数其实就是一个统计操作。

与简单的查询相比,统计操作不仅会消耗更多的 IO,还会消耗更多的 CPU 资源。

想象一下,有几亿人(其实没那么多,可能几十万就够了)去查剩余的票,即使机器不挂,机器所有的资源也会全力运行,而CPU 产生的热量可能在几分钟内就足够了。 稍微煮鸡蛋。

为了减少实时查询余票的开销,通常采用分时统计的方式来更新最新的统计信息。

当用户查询剩余票数信息时,查询到的是统计结果。 我已经分析了剩余的选票。 剩下的票是不可信的,所以有一定的延迟其实是允许的。

现在不能煮鸡蛋了,因为把上亿个统计请求变成一个统计请求,世界是不是一下子就安静了?

我们可以在12306首页看到剩余票数的行情数据

12306的数据库设计

主人小心,有怪物。 . .

1.需要统计剩余的票信息,查询会消耗较多的CPU和IO。

由于剩余的选票是不可信任的,所以实际上允许一定的延迟。 优化方式为异步统计,用户查询统计结果。

3张门票

与查询剩余车票相比,购票是从请求次数来分析的,比查询请求次数要少,因为一般来说,用户在选择合适日期的合适车次的车票之前,可能会查询很多次。

但是由于购票是一个事务,每个事务都会产生一个写操作,而这个事务并不是一个无限库存的事务,因为库存是有限的,所以设计的关键是降低粒度,减少锁冲突,以及减少数据扫描量。

其他需要考虑的因素包括

1. 同一辆火车上的同一个座位可能会在不同维度上多次出售

1.1 时间维度,比如出发日期

1.2 空间维度,起点不同

2.票价

票价一般与座位绑定,按区间计费。

12306数据流程图_12306用什么数据库_大数据 思考 12306

另一个要求是尽可能卖票,减少空座。

比如北京到上海的车路过(天津、徐州、南京、无锡、苏州),如果有人买了天津到南京的路段,剩下没买的路段要继续买。

如果北京到上海的火车,苏州到上海的车票都是用户买的,其他座位都不卖,铁哥会不会哭晕在厕所里?

或者某趟列车的大量座位被中途上车的用户购买,是否会减少全程可购买的车票数量?

这种情况之前就存在过,对于铁哥的成本来说也是一个不小的考验。

主人小心,有怪物。 . .

1、为了减少票务系统写锁冲突,比如同一个座位,尽量不要出现因为一个session在更新,其他session需要等待的情况。

(比如用户A买了北京到天津的公交车,用户B买了天津到上海同一趟火车的同一个座位,那么应该设计一个合理的merge操作(比如数据库内核改进)或者锁等待从设计中避免)

其实就是把座位的空间维度(从哪里到哪里)、自身的属性(座位号)、时间维度(出发日期)解耦,放到多条记录中,这样就可以在购买时同一时间。

因为目前数据库中最小的锁是行锁(一次只允许一个session更新单行记录,其他的都阻塞,等待释放锁),也许随着技术的发展,会演变成列锁,或者列锁中的元素(例如数组,JSON)。

4 增删改车

春节来临,一些热门线路通常要加班。

以及车次的增删改查。

在设计数据库时应考虑到这一点。

主人小心,有怪物。 . .

车次的变化会牵动全身。 比如剩余票数统计会相应变化,查询系统也会相应变化。

还有初始化信息的准备。 例如,为了加快购票速度,可以提前准备好车次的数据(可能每个座位一个记录)。 参考第三个要求的解释。

5 对账要求

可以通过支付宝、去哪儿、携程、铁路老板售票窗口、银行代理窗口、客运代理等多种渠道售票。

涉及实际销售信息和资金交易的对账要求。

通常这个操作是延迟第二天对账。

6 退改签要求

退票、改票也是比较普遍的需求,尤其是现在APP普及,退票、改票非常方便。

这导致用户可能会先买好一点的,尤其是春节期间,用户无法提前知道什么时候请假回家,所以先买几张不同日期的票,然后再退票或改票提前。

改签和退票涉及位置恢复(对于数据库来说,可能是更新数据),改签也涉及与购票相同的过程。

7 取票

这个很简单,就是根据用户ID查询已购买和未打印的票。

8种其他需求票

学生票、团体票、卧铺票、站票

这尤其适用于站票。 站票有上限。 需要控制一列火车的站票数量。

站票也有起点和终点之分,但有些用户可能买不到终点站的票,会先买一段,再补上,或者一直上车不下车,下车后再补上。

先上车再补车费

这种方法极其恶劣,但是很多人都是这样做的,未婚先孕,现在的年轻人。 . . .

通常考虑容积率,避免站票过多。

如果你不受控制地卖站票,你可能无法坐下。

猴哥,师父被妖怪抓走了

1. 大多数用户都有选择综合症。 一般来说,用户在选择合适日期的合适火车票之前可能会查询很多次。

查询量比较大,尤其是春节期间。

2.为了显示剩余票数,需要进行统计,会消耗较多的CPU和IO资源。

12306数据流程图_大数据 思考 12306_12306用什么数据库

3.需要进行路线规划,帮助用户找到符合条件(时间最短、行程最短、指定中转站、最便宜、或最少站票)等条件的换乘路线。

妈妈再也不用担心买不到票了。

4.需要统计剩余的票信息,查询会比较消耗CPU和IO。

由于剩余的选票是不可信任的,所以实际上允许一定的延迟。 优化方式为异步统计,用户查询统计结果。

5.为了减少票务系统写锁冲突,比如同一个座位,尽量不要出现一个session在更新,其他session需要等待的情况。

(比如用户A买了北京到天津的公交车,用户B买了天津到上海同一趟火车的同一个座位,那么应该设计一个合理的merge操作(比如数据库内核改进)或者锁等待从设计中避免)

其实就是把座位的空间维度(从哪里到哪里)、自身的属性(座位号)、时间维度(出发日期)解耦,放到多条记录中,这样就可以在购买时同一时间。

因为目前数据库中最小的锁是行锁(一次只允许一个session更新单行记录,其他的都阻塞,等待释放锁),也许随着技术的发展,会演变成列锁,或者列锁中的元素(例如数组,JSON)。

6、车次变更会牵动全身。 比如剩余票数统计会相应变化,查询系统也会相应变化。

还有初始化信息的准备。 例如,为了加快购票速度,可以提前准备好车次的数据(可能每个座位一个记录)。 参考第三个要求的解释。

基于以上痛点和需求分析,设计时应尽量避免锁等待,避免实时剩余票查询,避免空座。

2. 猴子请来的救助者是谁?

经过前面的分析,铁路售票系统最关键的业务场景已经描述完毕,设计痛点也已经说明,那么如何才能设计出一个合理的系统来满足亿万人群的抢票需求呢?

在西游记的每一集中,孙悟空大人都被妖怪抓走,总能找到救援人员来救他。

我们也需要救援人员,救援人员快来。 . . .

PostgreSQL 是全球最大的开源数据库,几乎适用于任何场景。

有许多功能可以用来加快开发效率并满足架构要求。

对于铁路售票系统,可以使用哪些保命法宝?

1.看招数,法宝1,变位型

使用 varbit 存储每个座位大道站点是否已为每次乘车售出。

例如,G1921次列车从北京到上海,途经天津、徐州、南京和苏州。 包括起点站在内,共6站。 然后用6位来表示。

'000000'     

如果我要买天津到徐州,这个值改成(下一站的BIT不用设置)

'010000'     

这个位置也可以卖北京到天津,徐州到码头的任何一站。

剩余车票统计也很方便,可以根据BIT对整个车次进行汇总计算。

统计任意站组合的剩余票数(北京-天津、北京-徐州、北京-南京、北京-苏州、北京-上海、天津-徐州、天津-南京、......、苏州-上海)

udf_count(varbit) returns record    

统计指定起点剩余车票(起点:北京,终点:南京;返程为京宁剩余车票)

udf_count(varbit, start, end) returns record    

针对以上两个需求,开发相应的聚合函数就可以了,其实就是对一些指定范围的bitands进行计数操作。

通过法宝1,解决了统计剩余票的需求和售票不缺口的需求。

2.看招数,法宝2,阵法

用一个数组存储每列火车的始发站和经过站。

使用数组存储的好处是可以通过数组的GIN索引快速检索到有哪些列车可用。

大数据 思考 12306_12306数据流程图_12306用什么数据库

比如查询北京到南京的火车班次。

select 车次 from 全国列车时刻表 where column_arr @> array['北京','南京'];  

这个SQL是可以索引的,效率很高。 每秒请求几十万不成问题。

法宝2解决高并发请求查询符合要求的列车信息。

3.观看花样,法宝3,跳过锁定

此功能是跳过锁定的行。 比如用户买北京到南京的车票,其实就是一个UPDATE ... SET BIT操作。

但很有可能其他用户也在购买,可能会出现锁冲突。 为了避免这种情况,可以skip locked,跳过lock conflicts,直接找别的座位。

select * from table   
  where column1='车次号'   -- 指定车次  
  and column2='车次日期'   -- 指定发车日期  
  -- and mod(pg_backend_pid(),100) = mod(pk,100)   -- 提高并发,如果有多个连接并发的在更新,可以直接分开落到不同的行,但是可能某些pID卖完了,可能会找不到票,建议不要开启这个条件  
  and column4='席别'  -- 指定席别  
  and getbit(column3, 开始站点位置, 结束站点位置-1) = '0...0'  -- 获取起始位置的BIT位,要求全部为0  
  order by column3 desc   -- 这个目的是先把已经卖了散票的的座位拿来卖,也符合铁大哥的思想,尽量把起点和重点的票卖出去,减少空洞  
  for update  
  skip locked  -- 跳过被锁的行,老牛逼了,不需要锁等待  
  limit ?;     -- 要买几张票  

神器3解决了一群人来抢票时,同一趟车的座位冲突问题。

4.看戏,法宝4,游标

如果要查询大量记录,可以使用游标来减少重复扫描。

5.看招数,法宝5,路径规划

如果用户选择了直达公交,且没有车票,它可以自动计算如何换乘,并根据用户的公交站点和目的地选择最佳路线。

参考pgrouting,符合物流的动态路径规划要求。

《聊聊双十一背后的技术——物流、动态路径规划》

6、看招数,法宝6、多核并行计算

开源还支持多核并行计算。 在生成余票统计时,为了提高生成速度,可以增加更多的CPU进行并行计算,快速得到余票统计。

比如你策划一本书,你已经做好了大纲,同时找了100个作者,这100个作者可以根据你布置的工作同时开始写作,很快就可以完成这本书。

在传统情况下,只有一个作者可以为你写一本书。 就算找到100个作者,其他99个也只能是免费的,或者只能写另外99本书。

7.看招数,法宝7,资源隔离

PostgreSQL是进程模型,因此可以控制每个进程的资源开销,包括(CPU、IOPS、MEMORY、网络)。 在铁路售票系统中,查询和售票是最关键的需求。 使用这种方法,您可以确保关键业务有足够的资源顺利运行。

这个思路和双十一镖局是一样的。 双十一期间,一些不必要的业务将被关闭12306用什么数据库,以保证主业的资源和顺畅的运行。

8.看招数,法宝8,分库分表

铁路数据已经达到了海量数据的水平,显然一台机器不可能存储所有的铁路数据。

那么该怎么办? 铁路数据可以分区存储在不同的主机上。

PostgreSQL有多种分库分表方案,如plproxy、pgpool-II、pg-xl、pg-xc、citus等。

9.看招数,法宝9,递归查询

铁路具有非常典型的上下文相关特征。 例如,一列火车经过N个车站,全国铁路组成一个庞大的铁路网。

12306用什么数据库_大数据 思考 12306_12306数据流程图

递归查询可以根据某个节点递归向上或向下查找相关站点。

比如哪些车可以直达北京,哪些车可以中转北京,或者查看从北京到拉萨可以走哪些路线和路线。

12306的数据库设计

10.看招数,法宝10,MPP,收工

为了不断提升12306的体验,铁哥还需要进行数据挖掘,比如今年春运应该增加哪些线路的车次,每天增加的车次,哪些线路可以减少春节前开行送用户回家。

这些问题可以通过基于过去运输数据的挖掘计算来回答。

基于PostgreSQL的MPP产品有很多,如Postgres-XL、Greenplum、Hawq、REDSHIFT、paraccl等。

使用PG可以很好的与这些产品集成,并保持语法一致。

降低数据分析的开发成本。

10件法宝一出,师傅又回来了。

别担心,还有更强大的。 阿里云在PostgreSQL的基础上做了很多改进。 例如,12306 系统具有特殊的定制功能。

3. 阿里云PostgreSQL varbit和数组增强介绍

在铁路售票系统中,有几个需求需要用到位和数组的特殊函数。 这些特殊功能目前在社区版本中不可用。 阿里云RDS PostgreSQL对此做了增强,如下。

1.剩余票数统计

计数指定的位范围 = 所有 0 计数

不指定范围,查询任意组合中所有位范围=0的个数

2.购票

指定要过滤、取出的位位置,并设置对应的位值

根据数组值获取其位置下标。

回头看之前写的两篇文章,也是使用varbit的应用场景,目的相同

《基于阿里云RDS PostgreSQL构建实时用户画像推荐系统》

《门禁广告销售系统需求分析与PostgreSQL数据库实现》

PostgreSQL的bit和array功能已经很强大了,阿里云RDS PostgreSQL的bitpack也是一个新的功能,需要用户在实际应用中细化。 大家一起来给阿里云提要求吧。

创建一个属于中国人的PostgreSQL。

概括

本文从铁路售票系统的需求出发,分析了售票系统的一些痛点以及设计数据库时需要注意的事项。

PostgreSQL的10大特性以及阿里云对PostgreSQL的改进可以很好的满足铁路票务系统的需求。

1、使用varbit存储每列火车的每个座位路线站是否已经售出。 解决了统计剩余票数的需求,以及售票无间隙的需求。

2.用数组存储每列火车的始发站和经过站。 数组类型支持索引,解决了高并发请求查询符合条件的列车信息的需求。

3.利用跳票锁定功能,解决了一群人来抢票时,同一趟车的座位冲突问题。

4.使用pgrouting路径规划功能解决智能推荐游乐设施需求。

同时,还可以应用于金融风控、刑事侦查、社会关系分析、网络分析等诸多场景。

有兴趣的话,网上有很多分析PostgreSQL、pgrouting、Neo4j的文章。 PostgreSQL 甚至比 Neo4j 更适合图场景。

5.多核并行计算,让更多的CPU帮你同时工作,比如快速异步剩余票统计。

6、减少空座的发生,保证更多人能买到满票。 (买票时,如果是中途票,尽量选择已经售出的中途票)

7、基于各个进程的资源隔离,可以提高稳定性。

8、连接HybridDB(基于GP\HAWQ)MPP系统,语法一致,可以支持iron

满足了道路系统的数据挖掘需求,节省了开发成本。

阿里云长期提供PostgreSQL、HybridDB(基于Greenplum、HAWQ)的服务和支持。

分类:

技术要点:

相关文章: