推理、部署与算力5641 字

12306超高并发如何保证数据一致性

·全库 437 / 611

《12306超高并发如何保证数据一致性》共 0.6 万字,通篇围绕 Redis、缓存、数据库、成本 展开,归在「推理、部署与算力」这一层。

覆盖Redis缓存数据库成本部署并发

适合要把模型跑起来,还得跑得起的人

目录骨架(3 节)
  1. 产品角度
  2. 技术角度
  3. 余票库存的表如何设计?
目录 · 5 节

12306 系统挑战

  • 创下全球最大实时票务交易系统世界记录,春运一个月抵欧洲一年。
  • 最高可达百万并发,承受了这个世界上能秒杀任何系统的 QPS。
  • 网站浏览量一天最高超 1500 亿次,峰值是双 11 的三倍。

12306 系统特点

  • 跟淘宝天猫等相比,业务简单(卖票)。
  • 流量极大。
  • 动态库存。

12306 系统难点

目前 12306 最大的难点,在于库存扣减。

它跟传统的电商网站,可能最大的不同在于它的库存, 它的库存是动态变化的,库存之间会互相影响。

比如现在有一个组合品的需求,A 品是由 B 品和 C 品通过不同的比例混合而成,用户下单的时候传过来的是 A 品这个 SKU,但是库存扣减的时候是把它的组合品的单品(B 和 C),都去扣一遍的。

我们平时各种商品 sku 库存的话,它是表里面的一行行记录。

image.png

某个行程是:杭州 -> 武汉 -> 成都。

杭州 -> 成都 ,武汉 -> 成都。这两个是一个车次。那么每卖出一张 武汉 -> 成都 的票,杭州 -> 成都 的票也会少一张。

image.png

举个极端的例子,火车上就一个座位,车次是从 A -> B -> C。

如果卖出 B -> C 的车票,不去扣减 A-> C 库存的话,那么假设有两个用户分别买了 A-> C 和 B -> C 。那么当车行至站点 B 的时候,车上会有两个人,但是座位就一个。

所以不同车次之间的库存是会互相影响的。

A -> B -> C -> D 共 4 个车站,假如乘客买了 B -> C 的车票,那么同时会影响到 A->C,A->D,B->C,B->D。

这里不会影响 A -> B 的行程,因为乘客买的是 B -> C 的车票,站点 B 才上车,不占用 A -> B 行程的座位,我下车你上车,不冲突。

计算耗费性能

一些长途,中间会经过十几个站点,而且有些城市是没有直达的车次的,中间只能换乘。涉及了多个车站的排列组合,这里计算是比较耗费性能的。

行锁竞争会非常激烈

image.png

购买一个行程会涉及多个站点的扣减库存,有可能这些多个站点的库存扣减是放在一个事务中的,如果是在一个事务中,那么一次下单行为,可能要涉及到几十次库存扣减。

锁范围膨胀,事务就会被拉大,线程数可能迅速被占满,导致数据库可能成为性能瓶颈,并且接口性能也会有所下降。

image.png

热点问题

火车站不同的站之间都是一个具体库存,中间的库存扣了之后,那么远的这个站的库存也要扣减。

极端情况下,一些热门城市,中间一些站点可能比较火爆,那两端的人是不是永远买不到票。

所以说像 12306 这种库存,其实涉及到非常多的一个行锁竞争,而且事务是非常大的。一列火车之间的库存其实是互相影响的,动态变化的。

另外还会涉及到其他维度,比如 硬座、硬卧、软卧、无座 这种业务逻辑在里面。

业务逻辑加上库存之间相互影响,就导致库存扣减逻辑异常复杂。

解决思路

产品角度

  • 早期的 12306 是通过整点去抢票,整点就会产生非常高的流量峰值,对系统造成非常大的压力,后面采取了分时段售票,比如今天开抢 15 天之后的车票,将抢票的压力按照时间区间分散开,大大减低了峰值。
  • 候补车票。

在 2019 年 5 月份,12306 新增了 “候补购票” 功能,在 “候补购票” 功能没出来之前,放票时间一到,千万人同时刷新抢票,这便是春运火车票秒光的原因。

候补车票堪称抢了一票第三方软件的 “饭碗”。

“黄牛” 的秘密武器是外挂,用最快的服务器不断地刷新和监控 12306,刷票速度往往是正常购票的几十倍。

实际上,市面上通行的 “抢票软件”,原理与“黄牛” 并无本质区别。

以前,合肥到上海的车票卖光了,有人退票或改签,车票会回到票池可供购买。抢票软件实时刷新监控,第一时间购买,这便是抢票软件比人快的原因。

现在,有了候补车票,合肥到上海的车票卖光了,乘客可以候补登记,有人退票或改签,车票按顺序优先卖给候补登记的人,而不是回到票池公开出售。这便是抢票软件无效的原因。

现在很多抢票软件反而没有 “候补购票” 功能抢票来得快。

候补车票在整个系统上相当于是一个异步过程。先排队,后面抢没抢到票再通知你。只要异步了,就可以通过消息,或者定时任务慢慢去消费,大大降低系统的压力。

image.png

12306 是有非常多的灰色流量的,像是一些抢票软件或者脚本。因为这里面涉及到的利益非常巨大,滋生了很多灰色流量,给 12306 本身带来了很多额外的压力。

“候补购票” 功能可以降低黄牛刷票行为,拦截部分灰色流量。

  • 验证码机制。BT 的验证码机制,可以过滤非常大的灰色流量。

12306 的验证码,是所有验证码中的一股绝对的 “清流”。

image.png

资料里没有你的场景?

把你手上的数据和想解决的那个环节发上来,我们按具体情况回,不复述方法论。

发布需求